Microsoft Azure IoTHub client MQTT transport

Dependents:   STM32F746_iothub_client_sample_mqtt FXOS8700CQ_To_Azure_IoT f767zi_mqtt FXOS8700CQ_To_Azure_IoT ... more

Files at this revision

API Documentation at this revision

Comitter:
AzureIoTClient
Date:
Tue Sep 11 11:12:42 2018 -0700
Parent:
40:cb03d6a6f46d
Commit message:
1.2.9

Changed in this revision

internal/iothub_client_retry_control.h Show annotated file Show diff for this revision Revisions of this file
iothub_client_retry_control.c Show annotated file Show diff for this revision Revisions of this file
iothubtransport_mqtt_common.c Show annotated file Show diff for this revision Revisions of this file
iothubtransportmqtt.c Show annotated file Show diff for this revision Revisions of this file
iothubtransportmqtt.h Show annotated file Show diff for this revision Revisions of this file
--- a/internal/iothub_client_retry_control.h	Tue Jun 26 19:14:02 2018 -0700
+++ b/internal/iothub_client_retry_control.h	Tue Sep 11 11:12:42 2018 -0700
@@ -23,9 +23,9 @@
 
 typedef enum RETRY_ACTION_TAG
 {
-	RETRY_ACTION_RETRY_NOW,
-	RETRY_ACTION_RETRY_LATER,
-	RETRY_ACTION_STOP_RETRYING
+    RETRY_ACTION_RETRY_NOW,
+    RETRY_ACTION_RETRY_LATER,
+    RETRY_ACTION_STOP_RETRYING
 } RETRY_ACTION;
 
 struct RETRY_CONTROL_INSTANCE_TAG;
@@ -44,4 +44,4 @@
 }
 #endif
 
-#endif // IOTHUB_CLIENT_RETRY_CONTROL 
\ No newline at end of file
+#endif // IOTHUB_CLIENT_RETRY_CONTROL
--- a/iothub_client_retry_control.c	Tue Jun 26 19:14:02 2018 -0700
+++ b/iothub_client_retry_control.c	Tue Sep 11 11:12:42 2018 -0700
@@ -15,16 +15,16 @@
 
 typedef struct RETRY_CONTROL_INSTANCE_TAG
 {
-	IOTHUB_CLIENT_RETRY_POLICY policy;
-	unsigned int max_retry_time_in_secs;
+    IOTHUB_CLIENT_RETRY_POLICY policy;
+    unsigned int max_retry_time_in_secs;
 
-	unsigned int initial_wait_time_in_secs;
-	unsigned int max_jitter_percent;
+    unsigned int initial_wait_time_in_secs;
+    unsigned int max_jitter_percent;
 
-	unsigned int retry_count;
-	time_t first_retry_time;
-	time_t last_retry_time;
-	unsigned int current_wait_time_in_secs;
+    unsigned int retry_count;
+    time_t first_retry_time;
+    time_t last_retry_time;
+    unsigned int current_wait_time_in_secs;
 } RETRY_CONTROL_INSTANCE;
 
 typedef int (*RETRY_ACTION_EVALUATION_FUNCTION)(RETRY_CONTROL_INSTANCE* retry_state, RETRY_ACTION* retry_action);
@@ -36,164 +36,164 @@
 
 static void* retry_control_clone_option(const char* name, const void* value)
 {
-	void* result;
+    void* result;
 
-	if ((name == NULL) || (value == NULL))
-	{
-		LogError("Failed to clone option (either name (%p) or value (%p) are NULL)", name, value);
-		result = NULL;
-	}
-	else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
-			strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
-	{
-		unsigned int* cloned_value;
+    if ((name == NULL) || (value == NULL))
+    {
+        LogError("Failed to clone option (either name (%p) or value (%p) are NULL)", name, value);
+        result = NULL;
+    }
+    else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
+            strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
+    {
+        unsigned int* cloned_value;
 
-		if ((cloned_value = (unsigned int*)malloc(sizeof(unsigned int))) == NULL)
-		{
-			LogError("Failed to clone option '%p' (malloc failed)", name);
-			result = NULL;
-		}
-		else
-		{
-			*cloned_value = *(unsigned int*)value;
+        if ((cloned_value = (unsigned int*)malloc(sizeof(unsigned int))) == NULL)
+        {
+            LogError("Failed to clone option '%p' (malloc failed)", name);
+            result = NULL;
+        }
+        else
+        {
+            *cloned_value = *(unsigned int*)value;
 
-			result = (void*)cloned_value;
-		}
-	}
-	else
-	{
-		LogError("Failed to clone option (option with name '%s' is not suppported)", name);
-		result = NULL;
-	}
+            result = (void*)cloned_value;
+        }
+    }
+    else
+    {
+        LogError("Failed to clone option (option with name '%s' is not suppported)", name);
+        result = NULL;
+    }
 
-	return result;
+    return result;
 }
 
 static void retry_control_destroy_option(const char* name, const void* value)
 {
-	if ((name == NULL) || (value == NULL))
-	{
-		LogError("Failed to destroy option (either name (%p) or value (%p) are NULL)", name, value);
-	}
-	else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
-		strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
-	{
-		free((void*)value);
-	}
-	else
-	{
-		LogError("Failed to destroy option (option with name '%s' is not suppported)", name);
-	}
+    if ((name == NULL) || (value == NULL))
+    {
+        LogError("Failed to destroy option (either name (%p) or value (%p) are NULL)", name, value);
+    }
+    else if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0 ||
+        strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
+    {
+        free((void*)value);
+    }
+    else
+    {
+        LogError("Failed to destroy option (option with name '%s' is not suppported)", name);
+    }
 }
 
 // ========== _should_retry() Auxiliary Functions ========== //
 
 static int evaluate_retry_action(RETRY_CONTROL_INSTANCE* retry_control, RETRY_ACTION* retry_action)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_019: [If `retry_control->retry_count` is 0, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
-	if (retry_control->retry_count == 0)
-	{
-		*retry_action = RETRY_ACTION_RETRY_NOW;
-		result = RESULT_OK;
-	}
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_020: [If `retry_control->last_retry_time` is INDEFINITE_TIME and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, the evaluation function shall return non-zero]
-	else if (retry_control->last_retry_time == INDEFINITE_TIME &&
-		     retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
-	{
-		LogError("Failed to evaluate retry action (last_retry_time is INDEFINITE_TIME)");
-		result = __FAILURE__;
-	}
-	else
-	{
-		time_t current_time;
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_019: [If `retry_control->retry_count` is 0, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
+    if (retry_control->retry_count == 0)
+    {
+        *retry_action = RETRY_ACTION_RETRY_NOW;
+        result = RESULT_OK;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_020: [If `retry_control->last_retry_time` is INDEFINITE_TIME and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, the evaluation function shall return non-zero]
+    else if (retry_control->last_retry_time == INDEFINITE_TIME &&
+             retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
+    {
+        LogError("Failed to evaluate retry action (last_retry_time is INDEFINITE_TIME)");
+        result = __FAILURE__;
+    }
+    else
+    {
+        time_t current_time;
 
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_021: [`current_time` shall be set using get_time()]
-		if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_022: [If get_time() fails, the evaluation function shall return non-zero]
-			LogError("Failed to evaluate retry action (get_time() failed)");
-			result = __FAILURE__;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_023: [If `retry_control->max_retry_time_in_secs` is not 0 and (`current_time` - `retry_control->first_retry_time`) is greater than or equal to `retry_control->max_retry_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_STOP_RETRYING]
-		else if (retry_control->max_retry_time_in_secs > 0 &&
-			get_difftime(current_time, retry_control->first_retry_time) >= retry_control->max_retry_time_in_secs)
-		{
-			*retry_action = RETRY_ACTION_STOP_RETRYING;
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_021: [`current_time` shall be set using get_time()]
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_022: [If get_time() fails, the evaluation function shall return non-zero]
+            LogError("Failed to evaluate retry action (get_time() failed)");
+            result = __FAILURE__;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_023: [If `retry_control->max_retry_time_in_secs` is not 0 and (`current_time` - `retry_control->first_retry_time`) is greater than or equal to `retry_control->max_retry_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_STOP_RETRYING]
+        else if (retry_control->max_retry_time_in_secs > 0 &&
+            get_difftime(current_time, retry_control->first_retry_time) >= retry_control->max_retry_time_in_secs)
+        {
+            *retry_action = RETRY_ACTION_STOP_RETRYING;
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
-			result = RESULT_OK;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_028: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_IMMEDIATE, retry_action shall be set to RETRY_ACTION_RETRY_NOW]
-		else if (retry_control->policy == IOTHUB_CLIENT_RETRY_IMMEDIATE)
-		{
-			*retry_action = RETRY_ACTION_RETRY_NOW;
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_028: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_IMMEDIATE, retry_action shall be set to RETRY_ACTION_RETRY_NOW]
+        else if (retry_control->policy == IOTHUB_CLIENT_RETRY_IMMEDIATE)
+        {
+            *retry_action = RETRY_ACTION_RETRY_NOW;
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
-			result = RESULT_OK;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_024: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is less than `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_LATER]
-		else if (get_difftime(current_time, retry_control->last_retry_time) < retry_control->current_wait_time_in_secs)
-		{
-			*retry_action = RETRY_ACTION_RETRY_LATER;
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_024: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is less than `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_LATER]
+        else if (get_difftime(current_time, retry_control->last_retry_time) < retry_control->current_wait_time_in_secs)
+        {
+            *retry_action = RETRY_ACTION_RETRY_LATER;
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
-			result = RESULT_OK;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_025: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is greater or equal to `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
-		else
-		{
-			*retry_action = RETRY_ACTION_RETRY_NOW;
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_025: [Otherwise, if (`current_time` - `retry_control->last_retry_time`) is greater or equal to `retry_control->current_wait_time_in_secs`, `retry_action` shall be set to RETRY_ACTION_RETRY_NOW]
+        else
+        {
+            *retry_action = RETRY_ACTION_RETRY_NOW;
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
-			result = RESULT_OK;
-		}
-	}
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_026: [If no errors occur, the evaluation function shall return 0]
+            result = RESULT_OK;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 static unsigned int calculate_next_wait_time(RETRY_CONTROL_INSTANCE* retry_control)
 {
-	unsigned int result;
+    unsigned int result;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_029: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_INTERVAL, `calculate_next_wait_time` shall return `retry_control->initial_wait_time_in_secs`]
-	if (retry_control->policy == IOTHUB_CLIENT_RETRY_INTERVAL)
-	{
-		result = retry_control->initial_wait_time_in_secs;
-	}
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_030: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (`retry_control->retry_count`))]
-	else if (retry_control->policy == IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF)
-	{
-		result = retry_control->initial_wait_time_in_secs * (retry_control->retry_count);
-	}
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_031: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF, `calculate_next_wait_time` shall return (pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`)]
-	else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF)
-	{
-		result = (unsigned int)(pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs);
-	}
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_032: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `calculate_next_wait_time` shall return ((pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`) * (1 + (`retry_control->max_jitter_percent` / 100) * (rand() / RAND_MAX)))]
-	else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
-	{
-		double jitter_percent = (retry_control->max_jitter_percent / 100.0) * (rand() / ((double)RAND_MAX));
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_029: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_INTERVAL, `calculate_next_wait_time` shall return `retry_control->initial_wait_time_in_secs`]
+    if (retry_control->policy == IOTHUB_CLIENT_RETRY_INTERVAL)
+    {
+        result = retry_control->initial_wait_time_in_secs;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_030: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (`retry_control->retry_count`))]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_LINEAR_BACKOFF)
+    {
+        result = retry_control->initial_wait_time_in_secs * (retry_control->retry_count);
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_031: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF, `calculate_next_wait_time` shall return (pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`)]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF)
+    {
+        result = (unsigned int)(pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs);
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_032: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `calculate_next_wait_time` shall return ((pow(2, `retry_control->retry_count` - 1) * `retry_control->initial_wait_time_in_secs`) * (1 + (`retry_control->max_jitter_percent` / 100) * (rand() / RAND_MAX)))]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
+    {
+        double jitter_percent = (retry_control->max_jitter_percent / 100.0) * (rand() / ((double)RAND_MAX));
 
-		result = (unsigned int)(pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs * (1 + jitter_percent));
-	}
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_033: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_RANDOM, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (rand() / RAND_MAX))]
-	else if (retry_control->policy == IOTHUB_CLIENT_RETRY_RANDOM)
-	{
-		double random_percent = ((double)rand() / (double)RAND_MAX);
-		result = (unsigned int)(retry_control->initial_wait_time_in_secs * random_percent);
-	}
-	else
-	{
-		LogError("Failed to calculate the next wait time (policy %d is not expected)", retry_control->policy);
+        result = (unsigned int)(pow(2, retry_control->retry_count - 1) * retry_control->initial_wait_time_in_secs * (1 + jitter_percent));
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_033: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_RANDOM, `calculate_next_wait_time` shall return (`retry_control->initial_wait_time_in_secs` * (rand() / RAND_MAX))]
+    else if (retry_control->policy == IOTHUB_CLIENT_RETRY_RANDOM)
+    {
+        double random_percent = ((double)rand() / (double)RAND_MAX);
+        result = (unsigned int)(retry_control->initial_wait_time_in_secs * random_percent);
+    }
+    else
+    {
+        LogError("Failed to calculate the next wait time (policy %d is not expected)", retry_control->policy);
 
-		result = 0;
-	}
+        result = 0;
+    }
 
-	return result;
+    return result;
 }
 
 
@@ -201,314 +201,314 @@
 
 int is_timeout_reached(time_t start_time, unsigned int timeout_in_secs, bool* is_timed_out)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_057: [If `start_time` is INDEFINITE_TIME, `is_timeout_reached` shall fail and return non-zero]
-	if (start_time == INDEFINITE_TIME)
-	{
-		LogError("Failed to verify timeout (start_time is INDEFINITE)");
-		result = __FAILURE__;
-	}
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_058: [If `is_timed_out` is NULL, `is_timeout_reached` shall fail and return non-zero]
-	else if (is_timed_out == NULL)
-	{
-		LogError("Failed to verify timeout (is_timed_out is NULL)");
-		result = __FAILURE__;
-	}
-	else
-	{
-		time_t current_time;
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_057: [If `start_time` is INDEFINITE_TIME, `is_timeout_reached` shall fail and return non-zero]
+    if (start_time == INDEFINITE_TIME)
+    {
+        LogError("Failed to verify timeout (start_time is INDEFINITE)");
+        result = __FAILURE__;
+    }
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_058: [If `is_timed_out` is NULL, `is_timeout_reached` shall fail and return non-zero]
+    else if (is_timed_out == NULL)
+    {
+        LogError("Failed to verify timeout (is_timed_out is NULL)");
+        result = __FAILURE__;
+    }
+    else
+    {
+        time_t current_time;
 
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_059: [`is_timeout_reached` shall obtain the `current_time` using get_time()]
-		if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_060: [If get_time() fails, `is_timeout_reached` shall fail and return non-zero]
-			LogError("Failed to verify timeout (get_time failed)");
-			result = __FAILURE__;
-		}
-		else
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_061: [If (`current_time` - `start_time`) is greater or equal to `timeout_in_secs`, `is_timed_out` shall be set to true]
-			if (get_difftime(current_time, start_time) >= timeout_in_secs)
-			{
-				*is_timed_out = true;
-			}
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_062: [If (`current_time` - `start_time`) is less than `timeout_in_secs`, `is_timed_out` shall be set to false]
-			else
-			{
-				*is_timed_out = false;
-			}
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_059: [`is_timeout_reached` shall obtain the `current_time` using get_time()]
+        if ((current_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_060: [If get_time() fails, `is_timeout_reached` shall fail and return non-zero]
+            LogError("Failed to verify timeout (get_time failed)");
+            result = __FAILURE__;
+        }
+        else
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_061: [If (`current_time` - `start_time`) is greater or equal to `timeout_in_secs`, `is_timed_out` shall be set to true]
+            if (get_difftime(current_time, start_time) >= timeout_in_secs)
+            {
+                *is_timed_out = true;
+            }
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_062: [If (`current_time` - `start_time`) is less than `timeout_in_secs`, `is_timed_out` shall be set to false]
+            else
+            {
+                *is_timed_out = false;
+            }
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_063: [If no errors occur, `is_timeout_reached` shall return 0]
-			result = RESULT_OK;
-		}
-	}
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_063: [If no errors occur, `is_timeout_reached` shall return 0]
+            result = RESULT_OK;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 void retry_control_reset(RETRY_CONTROL_HANDLE retry_control_handle)
 {
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_034: [If `retry_control_handle` is NULL, `retry_control_reset` shall return]
-	if (retry_control_handle == NULL)
-	{
-		LogError("Failed to reset the retry control (retry_state_handle is NULL)");
-	}
-	else
-	{
-		RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_034: [If `retry_control_handle` is NULL, `retry_control_reset` shall return]
+    if (retry_control_handle == NULL)
+    {
+        LogError("Failed to reset the retry control (retry_state_handle is NULL)");
+    }
+    else
+    {
+        RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
 
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_035: [`retry_control` shall have fields `retry_count` and `current_wait_time_in_secs` set to 0 (zero), `first_retry_time` and `last_retry_time` set to INDEFINITE_TIME]
-		retry_control->retry_count = 0;
-		retry_control->current_wait_time_in_secs = 0;
-		retry_control->first_retry_time = INDEFINITE_TIME;
-		retry_control->last_retry_time = INDEFINITE_TIME;
-	}
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_035: [`retry_control` shall have fields `retry_count` and `current_wait_time_in_secs` set to 0 (zero), `first_retry_time` and `last_retry_time` set to INDEFINITE_TIME]
+        retry_control->retry_count = 0;
+        retry_control->current_wait_time_in_secs = 0;
+        retry_control->first_retry_time = INDEFINITE_TIME;
+        retry_control->last_retry_time = INDEFINITE_TIME;
+    }
 }
 
 RETRY_CONTROL_HANDLE retry_control_create(IOTHUB_CLIENT_RETRY_POLICY policy, unsigned int max_retry_time_in_secs)
 {
-	RETRY_CONTROL_INSTANCE* retry_control;
+    RETRY_CONTROL_INSTANCE* retry_control;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_002: [`retry_control_create` shall allocate memory for the retry control instance structure (a.k.a. `retry_control`)]
-	if ((retry_control = (RETRY_CONTROL_INSTANCE*)malloc(sizeof(RETRY_CONTROL_INSTANCE))) == NULL)
-	{
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_003: [If malloc fails, `retry_control_create` shall fail and return NULL]
-		LogError("Failed creating the retry control (malloc failed)");
-	}
-	else
-	{
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_004: [The parameters passed to `retry_control_create` shall be saved into `retry_control`]
-		memset(retry_control, 0, sizeof(RETRY_CONTROL_INSTANCE));
-		retry_control->policy = policy;
-		retry_control->max_retry_time_in_secs = max_retry_time_in_secs;
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_002: [`retry_control_create` shall allocate memory for the retry control instance structure (a.k.a. `retry_control`)]
+    if ((retry_control = (RETRY_CONTROL_INSTANCE*)malloc(sizeof(RETRY_CONTROL_INSTANCE))) == NULL)
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_003: [If malloc fails, `retry_control_create` shall fail and return NULL]
+        LogError("Failed creating the retry control (malloc failed)");
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_004: [The parameters passed to `retry_control_create` shall be saved into `retry_control`]
+        memset(retry_control, 0, sizeof(RETRY_CONTROL_INSTANCE));
+        retry_control->policy = policy;
+        retry_control->max_retry_time_in_secs = max_retry_time_in_secs;
 
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_005: [If `policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF or IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `retry_control->initial_wait_time_in_secs` shall be set to 1]
-		if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF ||
-			retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
-		{
-			retry_control->initial_wait_time_in_secs = 1;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_006: [Otherwise `retry_control->initial_wait_time_in_secs` shall be set to 5]
-		else
-		{
-			retry_control->initial_wait_time_in_secs = 5;
-		}
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_005: [If `policy` is IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF or IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER, `retry_control->initial_wait_time_in_secs` shall be set to 1]
+        if (retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF ||
+            retry_control->policy == IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER)
+        {
+            retry_control->initial_wait_time_in_secs = 1;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_006: [Otherwise `retry_control->initial_wait_time_in_secs` shall be set to 5]
+        else
+        {
+            retry_control->initial_wait_time_in_secs = 5;
+        }
 
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_007: [`retry_control->max_jitter_percent` shall be set to 5]
-		retry_control->max_jitter_percent = 5;
-	
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_008: [The remaining fields in `retry_control` shall be initialized according to retry_control_reset()]
-		retry_control_reset(retry_control);
-	}
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_007: [`retry_control->max_jitter_percent` shall be set to 5]
+        retry_control->max_jitter_percent = 5;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_009: [If no errors occur, `retry_control_create` shall return a handle to `retry_control`]
-	return (RETRY_CONTROL_HANDLE)retry_control;
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_008: [The remaining fields in `retry_control` shall be initialized according to retry_control_reset()]
+        retry_control_reset(retry_control);
+    }
+
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_009: [If no errors occur, `retry_control_create` shall return a handle to `retry_control`]
+    return (RETRY_CONTROL_HANDLE)retry_control;
 }
 
 void retry_control_destroy(RETRY_CONTROL_HANDLE retry_control_handle)
 {
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_055: [If `retry_control_handle` is NULL, `retry_control_destroy` shall return]
-	if (retry_control_handle == NULL)
-	{
-		LogError("Failed to destroy the retry control (retry_control_handle is NULL)");
-	}
-	else
-	{
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_056: [`retry_control_destroy` shall destroy `retry_control_handle` using free()]
-		free(retry_control_handle);
-	}
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_055: [If `retry_control_handle` is NULL, `retry_control_destroy` shall return]
+    if (retry_control_handle == NULL)
+    {
+        LogError("Failed to destroy the retry control (retry_control_handle is NULL)");
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_056: [`retry_control_destroy` shall destroy `retry_control_handle` using free()]
+        free(retry_control_handle);
+    }
 }
 
 int retry_control_should_retry(RETRY_CONTROL_HANDLE retry_control_handle, RETRY_ACTION* retry_action)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_010: [If `retry_control_handle` or `retry_action` are NULL, `retry_control_should_retry` shall fail and return non-zero]
-	if ((retry_control_handle == NULL) || (retry_action == NULL))
-	{
-		LogError("Failed to evaluate if retry should be attempted (either retry_control_handle (%p) or retry_action (%p) are NULL)", retry_control_handle, retry_action);
-		result = __FAILURE__;
-	}
-	else
-	{
-		RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_010: [If `retry_control_handle` or `retry_action` are NULL, `retry_control_should_retry` shall fail and return non-zero]
+    if ((retry_control_handle == NULL) || (retry_action == NULL))
+    {
+        LogError("Failed to evaluate if retry should be attempted (either retry_control_handle (%p) or retry_action (%p) are NULL)", retry_control_handle, retry_action);
+        result = __FAILURE__;
+    }
+    else
+    {
+        RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
 
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_027: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_NONE, retry_action shall be set to RETRY_ACTION_STOP_RETRYING and return immediatelly with result 0]
-		if (retry_control->policy == IOTHUB_CLIENT_RETRY_NONE)
-		{
-			*retry_action = RETRY_ACTION_STOP_RETRYING;
-			result = RESULT_OK;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_011: [If `retry_control->first_retry_time` is INDEFINITE_TIME, it shall be set using get_time()]
-		else if (retry_control->first_retry_time == INDEFINITE_TIME && (retry_control->first_retry_time = get_time(NULL)) == INDEFINITE_TIME)
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_012: [If get_time() fails, `retry_control_should_retry` shall fail and return non-zero]
-			LogError("Failed to evaluate if retry should be attempted (get_time() failed)");
-			result = __FAILURE__;
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_013: [evaluate_retry_action() shall be invoked]
-		else if (evaluate_retry_action(retry_control, retry_action) != RESULT_OK)
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_014: [If evaluate_retry_action() fails, `retry_control_should_retry` shall fail and return non-zero]
-			LogError("Failed to evaluate if retry should be attempted (evaluate_retry_action() failed)");
-			result = __FAILURE__;
-		}
-		else
-		{
-			if (*retry_action == RETRY_ACTION_RETRY_NOW)
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_015: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW, `retry_control->retry_count` shall be incremented by 1]
-				retry_control->retry_count++;
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_027: [If `retry_control->policy` is IOTHUB_CLIENT_RETRY_NONE, retry_action shall be set to RETRY_ACTION_STOP_RETRYING and return immediatelly with result 0]
+        if (retry_control->policy == IOTHUB_CLIENT_RETRY_NONE)
+        {
+            *retry_action = RETRY_ACTION_STOP_RETRYING;
+            result = RESULT_OK;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_011: [If `retry_control->first_retry_time` is INDEFINITE_TIME, it shall be set using get_time()]
+        else if (retry_control->first_retry_time == INDEFINITE_TIME && (retry_control->first_retry_time = get_time(NULL)) == INDEFINITE_TIME)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_012: [If get_time() fails, `retry_control_should_retry` shall fail and return non-zero]
+            LogError("Failed to evaluate if retry should be attempted (get_time() failed)");
+            result = __FAILURE__;
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_013: [evaluate_retry_action() shall be invoked]
+        else if (evaluate_retry_action(retry_control, retry_action) != RESULT_OK)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_014: [If evaluate_retry_action() fails, `retry_control_should_retry` shall fail and return non-zero]
+            LogError("Failed to evaluate if retry should be attempted (evaluate_retry_action() failed)");
+            result = __FAILURE__;
+        }
+        else
+        {
+            if (*retry_action == RETRY_ACTION_RETRY_NOW)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_015: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW, `retry_control->retry_count` shall be incremented by 1]
+                retry_control->retry_count++;
 
-				if (retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
-				{
-					// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_016: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->last_retry_time` shall be set using get_time()]
-					retry_control->last_retry_time = get_time(NULL);
+                if (retry_control->policy != IOTHUB_CLIENT_RETRY_IMMEDIATE)
+                {
+                    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_016: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->last_retry_time` shall be set using get_time()]
+                    retry_control->last_retry_time = get_time(NULL);
 
-					// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_017: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->current_wait_time_in_secs` shall be set using calculate_next_wait_time()]
-					retry_control->current_wait_time_in_secs = calculate_next_wait_time(retry_control);
-				}
-			}
+                    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_017: [If `retry_action` is set to RETRY_ACTION_RETRY_NOW and policy is not IOTHUB_CLIENT_RETRY_IMMEDIATE, `retry_control->current_wait_time_in_secs` shall be set using calculate_next_wait_time()]
+                    retry_control->current_wait_time_in_secs = calculate_next_wait_time(retry_control);
+                }
+            }
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_018: [If no errors occur, `retry_control_should_retry` shall return 0]
-			result = RESULT_OK;
-		}
-	}
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_018: [If no errors occur, `retry_control_should_retry` shall return 0]
+            result = RESULT_OK;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 int retry_control_set_option(RETRY_CONTROL_HANDLE retry_control_handle, const char* name, const void* value)
 {
-	int result;
+    int result;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_036: [If `retry_control_handle`, `name` or `value` are NULL, `retry_control_set_option` shall fail and return non-zero]
-	if (retry_control_handle == NULL || name == NULL || value == NULL)
-	{
-		LogError("Failed to set option (either retry_state_handle (%p), name (%p) or value (%p) are NULL)", retry_control_handle, name, value);
-		result = __FAILURE__;
-	}
-	else
-	{
-		RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_036: [If `retry_control_handle`, `name` or `value` are NULL, `retry_control_set_option` shall fail and return non-zero]
+    if (retry_control_handle == NULL || name == NULL || value == NULL)
+    {
+        LogError("Failed to set option (either retry_state_handle (%p), name (%p) or value (%p) are NULL)", retry_control_handle, name, value);
+        result = __FAILURE__;
+    }
+    else
+    {
+        RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
 
-		if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0)
-		{
-			unsigned int cast_value = *((unsigned int*)value);
+        if (strcmp(RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, name) == 0)
+        {
+            unsigned int cast_value = *((unsigned int*)value);
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_037: [If `name` is "initial_wait_time_in_secs" and `value` is less than 1, `retry_control_set_option` shall fail and return non-zero]
-			if (cast_value < 1)
-			{
-				LogError("Failed to set option '%s' (value must be equal or greater to 1)", name);
-				result = __FAILURE__;
-			}
-			else
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_038: [If `name` is "initial_wait_time_in_secs", `value` shall be saved on `retry_control->initial_wait_time_in_secs`]
-				retry_control->initial_wait_time_in_secs = cast_value;
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_037: [If `name` is "initial_wait_time_in_secs" and `value` is less than 1, `retry_control_set_option` shall fail and return non-zero]
+            if (cast_value < 1)
+            {
+                LogError("Failed to set option '%s' (value must be equal or greater to 1)", name);
+                result = __FAILURE__;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_038: [If `name` is "initial_wait_time_in_secs", `value` shall be saved on `retry_control->initial_wait_time_in_secs`]
+                retry_control->initial_wait_time_in_secs = cast_value;
 
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
-				result = RESULT_OK;
-			}
-		}
-		else if (strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
-		{
-			unsigned int cast_value = *((unsigned int*)value);
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
+                result = RESULT_OK;
+            }
+        }
+        else if (strcmp(RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, name) == 0)
+        {
+            unsigned int cast_value = *((unsigned int*)value);
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_039: [If `name` is "max_jitter_percent" and `value` is less than 0 or greater than 100, `retry_control_set_option` shall fail and return non-zero]
-			if (cast_value > 100) // it's unsigned int, it doesn't need to be checked for less than zero.
-			{
-				LogError("Failed to set option '%s' (value must be in the range 0 to 100)", name);
-				result = __FAILURE__;
-			}
-			else
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_040: [If `name` is "max_jitter_percent", value shall be saved on `retry_control->max_jitter_percent`]
-				retry_control->max_jitter_percent = cast_value;
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_039: [If `name` is "max_jitter_percent" and `value` is less than 0 or greater than 100, `retry_control_set_option` shall fail and return non-zero]
+            if (cast_value > 100) // it's unsigned int, it doesn't need to be checked for less than zero.
+            {
+                LogError("Failed to set option '%s' (value must be in the range 0 to 100)", name);
+                result = __FAILURE__;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_040: [If `name` is "max_jitter_percent", value shall be saved on `retry_control->max_jitter_percent`]
+                retry_control->max_jitter_percent = cast_value;
 
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
-				result = RESULT_OK;
-			}
-		}
-		else if (strcmp(RETRY_CONTROL_OPTION_SAVED_OPTIONS, name) == 0)
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_041: [If `name` is "retry_control_options", value shall be fed to `retry_control` using OptionHandler_FeedOptions]
-			if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, retry_control_handle) != OPTIONHANDLER_OK)
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_042: [If OptionHandler_FeedOptions fails, `retry_control_set_option` shall fail and return non-zero]
-				LogError("messenger_set_option failed (OptionHandler_FeedOptions failed)");
-				result = __FAILURE__;
-			}
-			else
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, `retry_control_set_option` shall return 0]
-				result = RESULT_OK;
-			}
-		}
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_043: [If `name` is not a supported option, `retry_control_set_option` shall fail and return non-zero]
-		else
-		{
-			LogError("messenger_set_option failed (option with name '%s' is not suppported)", name);
-			result = __FAILURE__;
-		}
-	}
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, retry_control_set_option shall return 0]
+                result = RESULT_OK;
+            }
+        }
+        else if (strcmp(RETRY_CONTROL_OPTION_SAVED_OPTIONS, name) == 0)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_041: [If `name` is "retry_control_options", value shall be fed to `retry_control` using OptionHandler_FeedOptions]
+            if (OptionHandler_FeedOptions((OPTIONHANDLER_HANDLE)value, retry_control_handle) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_042: [If OptionHandler_FeedOptions fails, `retry_control_set_option` shall fail and return non-zero]
+                LogError("messenger_set_option failed (OptionHandler_FeedOptions failed)");
+                result = __FAILURE__;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_044: [If no errors occur, `retry_control_set_option` shall return 0]
+                result = RESULT_OK;
+            }
+        }
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_043: [If `name` is not a supported option, `retry_control_set_option` shall fail and return non-zero]
+        else
+        {
+            LogError("messenger_set_option failed (option with name '%s' is not suppported)", name);
+            result = __FAILURE__;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 OPTIONHANDLER_HANDLE retry_control_retrieve_options(RETRY_CONTROL_HANDLE retry_control_handle)
 {
-	OPTIONHANDLER_HANDLE result;
+    OPTIONHANDLER_HANDLE result;
 
-	// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_045: [If `retry_control_handle`, `retry_control_retrieve_options` shall fail and return NULL]
-	if (retry_control_handle == NULL)
-	{
-		LogError("Failed to retrieve options (retry_state_handle is NULL)");
-		result = NULL;
-	}
-	else
-	{
-		// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_046: [An instance of OPTIONHANDLER_HANDLE (a.k.a. `options`) shall be created using OptionHandler_Create]
-		OPTIONHANDLER_HANDLE options = OptionHandler_Create(retry_control_clone_option, retry_control_destroy_option, (pfSetOption)retry_control_set_option);
+    // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_045: [If `retry_control_handle`, `retry_control_retrieve_options` shall fail and return NULL]
+    if (retry_control_handle == NULL)
+    {
+        LogError("Failed to retrieve options (retry_state_handle is NULL)");
+        result = NULL;
+    }
+    else
+    {
+        // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_046: [An instance of OPTIONHANDLER_HANDLE (a.k.a. `options`) shall be created using OptionHandler_Create]
+        OPTIONHANDLER_HANDLE options = OptionHandler_Create(retry_control_clone_option, retry_control_destroy_option, (pfSetOption)retry_control_set_option);
 
-		if (options == NULL)
-		{
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_047: [If OptionHandler_Create fails, `retry_control_retrieve_options` shall fail and return NULL]
-			LogError("Failed to retrieve options (OptionHandler_Create failed)");
-			result = NULL;
-		}
-		else
-		{
-			RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
+        if (options == NULL)
+        {
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_047: [If OptionHandler_Create fails, `retry_control_retrieve_options` shall fail and return NULL]
+            LogError("Failed to retrieve options (OptionHandler_Create failed)");
+            result = NULL;
+        }
+        else
+        {
+            RETRY_CONTROL_INSTANCE* retry_control = (RETRY_CONTROL_INSTANCE*)retry_control_handle;
 
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_050: [`retry_control->initial_wait_time_in_secs` shall be added to `options` using OptionHandler_Add]
-			if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, (void*)&retry_control->initial_wait_time_in_secs) != OPTIONHANDLER_OK)
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
-				LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
-				result = NULL;
-			}
-			// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_051: [`retry_control->max_jitter_percent` shall be added to `options` using OptionHandler_Add]
-			else if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, (void*)&retry_control->max_jitter_percent) != OPTIONHANDLER_OK)
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
-				LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
-				result = NULL;
-			}
-			else
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_054: [If no errors occur, `retry_control_retrieve_options` shall return the OPTIONHANDLER_HANDLE instance]
-				result = options;
-			}
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_050: [`retry_control->initial_wait_time_in_secs` shall be added to `options` using OptionHandler_Add]
+            if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS, (void*)&retry_control->initial_wait_time_in_secs) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
+                LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
+                result = NULL;
+            }
+            // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_051: [`retry_control->max_jitter_percent` shall be added to `options` using OptionHandler_Add]
+            else if (OptionHandler_AddOption(options, RETRY_CONTROL_OPTION_MAX_JITTER_PERCENT, (void*)&retry_control->max_jitter_percent) != OPTIONHANDLER_OK)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_052: [If any call to OptionHandler_Add fails, `retry_control_retrieve_options` shall fail and return NULL]
+                LogError("Failed to retrieve options (OptionHandler_Create failed for option '%s')", RETRY_CONTROL_OPTION_INITIAL_WAIT_TIME_IN_SECS);
+                result = NULL;
+            }
+            else
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_054: [If no errors occur, `retry_control_retrieve_options` shall return the OPTIONHANDLER_HANDLE instance]
+                result = options;
+            }
 
-			if (result == NULL)
-			{
-				// Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_053: [If any failures occur, `retry_control_retrieve_options` shall release any memory it has allocated]
-				OptionHandler_Destroy(options);
-			}
-		}
-	}
+            if (result == NULL)
+            {
+                // Codes_SRS_IOTHUB_CLIENT_RETRY_CONTROL_09_053: [If any failures occur, `retry_control_retrieve_options` shall release any memory it has allocated]
+                OptionHandler_Destroy(options);
+            }
+        }
+    }
 
-	return result;
-}
\ No newline at end of file
+    return result;
+}
--- a/iothubtransport_mqtt_common.c	Tue Jun 26 19:14:02 2018 -0700
+++ b/iothubtransport_mqtt_common.c	Tue Sep 11 11:12:42 2018 -0700
@@ -11,6 +11,7 @@
 #include "azure_c_shared_utility/doublylinkedlist.h"
 #include "azure_c_shared_utility/crt_abstractions.h"
 #include "azure_c_shared_utility/agenttime.h"
+#include "azure_c_shared_utility/threadapi.h"
 
 #include "iothub_client_core_ll.h"
 #include "iothub_client_options.h"
@@ -52,6 +53,7 @@
 
 #define DEFAULT_RETRY_POLICY                IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER
 #define DEFAULT_RETRY_TIMEOUT_IN_SECONDS    0
+#define MAX_DISCONNECT_VALUE                50
 
 static const char TOPIC_DEVICE_TWIN_PREFIX[] = "$iothub/twin";
 static const char TOPIC_DEVICE_METHOD_PREFIX[] = "$iothub/methods";
@@ -165,6 +167,7 @@
     STRING_HANDLE module_id;
     STRING_HANDLE devicesAndModulesPath;
     int portNum;
+    bool conn_attempted;
 
     MQTT_GET_IO_TRANSPORT get_io_transport;
 
@@ -179,18 +182,20 @@
     // Upper layer
     IOTHUB_CLIENT_CORE_LL_HANDLE llClientHandle;
 
-    // Protocol 
+    // Protocol
     MQTT_CLIENT_HANDLE mqttClient;
     XIO_HANDLE xioTransport;
 
     // Session - connection
     uint16_t packetId;
+    uint16_t twin_resp_packet_id;
 
     // Connection state control
     bool isRegistered;
     MQTT_CLIENT_STATUS mqttClientStatus;
     bool isDestroyCalled;
     bool device_twin_get_sent;
+    bool twin_resp_sub_recv;
     bool isRecoverableError;
     uint16_t keepAliveValue;
     uint16_t connect_timeout_in_sec;
@@ -300,7 +305,7 @@
     set_saved_tls_options(transport_data, NULL);
 
     tickcounter_destroy(transport_data->msgTickCounter);
-    
+
     free_proxy_data(transport_data);
 
     STRING_delete(transport_data->devicesAndModulesPath);
@@ -314,7 +319,7 @@
     STRING_delete(transport_data->topic_NotifyState);
     STRING_delete(transport_data->topic_DeviceMethods);
     STRING_delete(transport_data->topic_InputQueue);
-    
+
     free(transport_data);
 }
 
@@ -357,7 +362,7 @@
 
 static uint16_t get_next_packet_id(PMQTTTRANSPORT_HANDLE_DATA transport_data)
 {
-    if (transport_data->packetId+1 >= USHRT_MAX)
+    if (transport_data->packetId + 1 >= USHRT_MAX)
     {
         transport_data->packetId = 1;
     }
@@ -368,6 +373,7 @@
     return transport_data->packetId;
 }
 
+#ifndef NO_LOGGING
 static const char* retrieve_mqtt_return_codes(CONNECT_RETURN_CODE rtn_code)
 {
     switch (rtn_code)
@@ -389,6 +395,7 @@
             return "Unknown";
     }
 }
+#endif // NO_LOGGING
 
 static int retrieve_device_method_rid_info(const char* resp_topic, STRING_HANDLE method_name, STRING_HANDLE request_id)
 {
@@ -430,7 +437,7 @@
                         const char* request_id_value = STRING_c_str(token_value);
                         if (memcmp(request_id_value, REQUEST_ID_PROPERTY, request_id_length) == 0)
                         {
-                            if (STRING_concat(request_id, request_id_value+request_id_length) != 0)
+                            if (STRING_concat(request_id, request_id_value + request_id_length) != 0)
                             {
                                 LogError("Failed STRING_concat failed.");
                                 result = __FAILURE__;
@@ -527,7 +534,7 @@
     {
         result = 0;
 
-        while(n-- && result == 0)
+        while (n-- && result == 0)
         {
             if (*s1 == 0) result = -1;
             else if (*s2 == 0) result = 1;
@@ -548,16 +555,16 @@
 static IOTHUB_IDENTITY_TYPE retrieve_topic_type(const char* topic_resp, const char* input_queue)
 {
     IOTHUB_IDENTITY_TYPE type;
-    if (InternStrnicmp(topic_resp, TOPIC_DEVICE_TWIN_PREFIX, sizeof(TOPIC_DEVICE_TWIN_PREFIX)-1) == 0)
+    if (InternStrnicmp(topic_resp, TOPIC_DEVICE_TWIN_PREFIX, sizeof(TOPIC_DEVICE_TWIN_PREFIX) - 1) == 0)
     {
         type = IOTHUB_TYPE_DEVICE_TWIN;
     }
-    else if (InternStrnicmp(topic_resp, TOPIC_DEVICE_METHOD_PREFIX, sizeof(TOPIC_DEVICE_METHOD_PREFIX)-1) == 0)
+    else if (InternStrnicmp(topic_resp, TOPIC_DEVICE_METHOD_PREFIX, sizeof(TOPIC_DEVICE_METHOD_PREFIX) - 1) == 0)
     {
         type = IOTHUB_TYPE_DEVICE_METHODS;
     }
     // input_queue contains additional "#" from subscribe, which we strip off on comparing incoming.
-    else if ((input_queue != NULL) && InternStrnicmp(topic_resp, input_queue, strlen(input_queue)-1) == 0)
+    else if ((input_queue != NULL) && InternStrnicmp(topic_resp, input_queue, strlen(input_queue) - 1) == 0)
     {
         type = IOTHUB_TYPE_EVENT_QUEUE;
     }
@@ -871,7 +878,7 @@
     int result;
     uint16_t packet_id = get_next_packet_id(transport_data);
 
-    STRING_HANDLE msg_topic = STRING_construct_sprintf(DEVICE_METHOD_RESPONSE_TOPIC, status_code, STRING_c_str(request_id) );
+    STRING_HANDLE msg_topic = STRING_construct_sprintf(DEVICE_METHOD_RESPONSE_TOPIC, status_code, STRING_c_str(request_id));
     if (msg_topic == NULL)
     {
         LogError("Failed constructing message topic.");
@@ -1005,10 +1012,53 @@
     return result;
 }
 
+static void changeStateToSubscribeIfAllowed(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    if (transport_data->currPacketState != CONNACK_TYPE &&
+        transport_data->currPacketState != CONNECT_TYPE &&
+        transport_data->currPacketState != DISCONNECT_TYPE &&
+        transport_data->currPacketState != PACKET_TYPE_ERROR)
+    {
+        transport_data->currPacketState = SUBSCRIBE_TYPE;
+    }
+}
+
+static int subscribeToNotifyStateIfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
+{
+    int result;
+
+    if (transport_data->topic_NotifyState == NULL)
+    {
+        transport_data->topic_NotifyState = STRING_construct(TOPIC_NOTIFICATION_STATE);
+        if (transport_data->topic_NotifyState == NULL)
+        {
+            LogError("Failure: unable constructing notify state topic");
+            result = __FAILURE__;
+        }
+        else
+        {
+            transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
+            result = 0;
+        }
+    }
+    else
+    {
+        result = 0;
+    }
+
+    if (result == 0)
+    {
+        changeStateToSubscribeIfAllowed(transport_data);
+    }
+
+    return result;
+}
+
+
 static bool isSystemProperty(const char* tokenData)
 {
     bool result = false;
-    size_t propCount = sizeof(sysPropList)/sizeof(sysPropList[0]);
+    size_t propCount = sizeof(sysPropList) / sizeof(sysPropList[0]);
     size_t index = 0;
     for (index = 0; index < propCount; index++)
     {
@@ -1069,7 +1119,7 @@
             result = __FAILURE__;
         }
         STRING_TOKENIZER_destroy(token_handle);
-     }
+    }
 
     return result;
 }
@@ -1078,7 +1128,7 @@
 {
     // Not finding a system property to map to isn't an error.
     int result = 0;
-    
+
     if (nameLen > 4)
     {
         if (strcmp((const char*)&propName[nameLen - 4], CONNECTION_DEVICE_ID) == 0)
@@ -1213,10 +1263,10 @@
                                         }
                                         else
                                         {
-                                            strncpy(propName, tokenData, nameLen);
+                                            memcpy(propName, tokenData, nameLen);
                                             propName[nameLen] = '\0';
 
-                                            strncpy(propValue, iterator + 1, valLen);
+                                            memcpy(propValue, iterator + 1, valLen);
                                             propValue[valLen] = '\0';
 
                                             if (urldecode)
@@ -1270,10 +1320,10 @@
                                         }
                                         else
                                         {
-                                            strncpy(propName, tokenData, nameLen);
+                                            memcpy(propName, tokenData, nameLen);
                                             propName[nameLen] = '\0';
 
-                                            strncpy(propValue, iterator + 1, valLen);
+                                            memcpy(propValue, iterator + 1, valLen);
                                             propValue[valLen] = '\0';
 
                                             if (urldecode)
@@ -1374,6 +1424,8 @@
                                 {
                                     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ If type is IOTHUB_TYPE_DEVICE_TWIN, then on success if msg_type is RETRIEVE_PROPERTIES then mqtt_notification_callback shall call IoTHubClientCore_LL_RetrievePropertyComplete... ] */
                                     IoTHubClientCore_LL_RetrievePropertyComplete(transportData->llClientHandle, DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length);
+                                    // Only after receiving device twin request should we start listening for patches.
+                                    (void)subscribeToNotifyStateIfNeeded(transportData);
                                 }
                                 else
                                 {
@@ -1397,7 +1449,7 @@
                 }
                 else
                 {
-                    DEVICE_METHOD_INFO* dev_method_info = malloc(sizeof(DEVICE_METHOD_INFO) );
+                    DEVICE_METHOD_INFO* dev_method_info = malloc(sizeof(DEVICE_METHOD_INFO));
                     if (dev_method_info == NULL)
                     {
                         LogError("Failure: allocating DEVICE_METHOD_INFO object");
@@ -1564,7 +1616,7 @@
                         {
                             transport_data->isRecoverableError = false;
                         }
-                        LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieve_mqtt_return_codes(connack->returnCode) );
+                        LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieve_mqtt_return_codes(connack->returnCode));
                         transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_PENDING_CLOSE;
                         transport_data->currPacketState = PACKET_TYPE_ERROR;
                     }
@@ -1590,6 +1642,12 @@
                     }
                     // The connect packet has been acked
                     transport_data->currPacketState = SUBACK_TYPE;
+
+                    // Is this a twin message
+                    if (suback->packetId == transport_data->twin_resp_packet_id)
+                    {
+                        transport_data->twin_resp_sub_recv = true;
+                    }
                 }
                 else
                 {
@@ -1615,17 +1673,17 @@
             default:
             {
                 break;
-            } 
+            }
         }
     }
 }
 
-// Prior to creating a new connection, if we have an existing xioTransport we need to clear 
-// it now or else cached settings (especially TLS when communicating with HTTP proxies) will 
-// break reconnection attempt.  
+// Prior to creating a new connection, if we have an existing xioTransport that has been connected before
+// we need to clear it now or else cached settings (especially TLS when communicating with HTTP proxies)
+// will break reconnection attempt.
 static void ResetConnectionIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
 {
-    if (transport_data->xioTransport != NULL)
+    if (transport_data->xioTransport != NULL && transport_data->conn_attempted)
     {
         OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
         set_saved_tls_options(transport_data, options);
@@ -1635,6 +1693,15 @@
     }
 }
 
+static void mqtt_disconnect_cb(void* ctx)
+{
+    if (ctx != NULL)
+    {
+        int* disconn_recv = (int*)ctx;
+        *disconn_recv = 1;
+    }
+}
+
 static void DisconnectFromClient(PMQTTTRANSPORT_HANDLE_DATA transport_data)
 {
     if (!transport_data->isDestroyCalled)
@@ -1642,8 +1709,19 @@
         OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
         set_saved_tls_options(transport_data, options);
     }
-
-    (void)mqtt_client_disconnect(transport_data->mqttClient, NULL, NULL);
+    // Ensure the disconnect message is sent
+    if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_CONNECTED)
+    {
+        int disconn_recv = 0;
+        (void)mqtt_client_disconnect(transport_data->mqttClient, mqtt_disconnect_cb, &disconn_recv);
+        size_t disconnect_ctr = 0;
+        do
+        {
+            mqtt_client_dowork(transport_data->mqttClient);
+            disconnect_ctr++;
+            ThreadAPI_Sleep(50);
+        } while ((disconnect_ctr < MAX_DISCONNECT_VALUE) && (disconn_recv == 0));
+    }
     xio_destroy(transport_data->xioTransport);
     transport_data->xioTransport = NULL;
 
@@ -1677,7 +1755,7 @@
             }
             case MQTT_CLIENT_PARSE_ERROR:
             case MQTT_CLIENT_MEMORY_ERROR:
-            case MQTT_CLIENT_UNKNOWN_ERROR: 
+            case MQTT_CLIENT_UNKNOWN_ERROR:
             {
                 LogError("INTERNAL ERROR: unexpected error value received %s", ENUM_TO_STRING(MQTT_CLIENT_EVENT_ERROR, error));
                 break;
@@ -1722,6 +1800,7 @@
     {
         uint32_t topic_subscription = 0;
         size_t subscribe_count = 0;
+        uint16_t packet_id = get_next_packet_id(transport_data);
         SUBSCRIBE_PAYLOAD subscribe[SUBSCRIBE_TOPIC_COUNT];
         if ((transport_data->topic_MqttMessage != NULL) && (SUBSCRIBE_TELEMETRY_TOPIC & transport_data->topics_ToSubscribe))
         {
@@ -1736,6 +1815,7 @@
             subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
             topic_subscription |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
             subscribe_count++;
+            transport_data->twin_resp_packet_id = packet_id;
         }
         if ((transport_data->topic_NotifyState != NULL) && (SUBSCRIBE_NOTIFICATION_STATE_TOPIC & transport_data->topics_ToSubscribe))
         {
@@ -1762,7 +1842,7 @@
         if (subscribe_count != 0)
         {
             /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransport_MQTT_Common_Subscribe shall call mqtt_client_subscribe to subscribe to the Message Topic.] */
-            if (mqtt_client_subscribe(transport_data->mqttClient, get_next_packet_id(transport_data), subscribe, subscribe_count) != 0)
+            if (mqtt_client_subscribe(transport_data->mqttClient, packet_id, subscribe, subscribe_count) != 0)
             {
                 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
                 LogError("Failure: mqtt_client_subscribe returned error.");
@@ -1787,37 +1867,41 @@
     }
 }
 
-static const unsigned char* RetrieveMessagePayload(IOTHUB_MESSAGE_HANDLE messageHandle, size_t* length)
+static bool RetrieveMessagePayload(IOTHUB_MESSAGE_HANDLE messageHandle, const unsigned char** payload, size_t* length)
 {
-    const unsigned char* result;
-
+    bool result;
     IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(messageHandle);
     if (contentType == IOTHUBMESSAGE_BYTEARRAY)
     {
-        if (IoTHubMessage_GetByteArray(messageHandle, &result, length) != IOTHUB_MESSAGE_OK)
+        if (IoTHubMessage_GetByteArray(messageHandle, &(*payload), length) != IOTHUB_MESSAGE_OK)
         {
             LogError("Failure result from IoTHubMessage_GetByteArray");
-            result = NULL;
+            result = false;
             *length = 0;
         }
+        else
+        {
+            result = true;
+        }
     }
     else if (contentType == IOTHUBMESSAGE_STRING)
     {
-        result = (const unsigned char*)IoTHubMessage_GetString(messageHandle);
-        if (result == NULL)
+        *payload = (const unsigned char*)IoTHubMessage_GetString(messageHandle);
+        if (*payload == NULL)
         {
             LogError("Failure result from IoTHubMessage_GetString");
-            result = NULL;
+            result = false;
             *length = 0;
         }
         else
         {
-            *length = strlen((const char*)result);
+            *length = strlen((const char*)*payload);
+            result = true;
         }
     }
     else
     {
-        result = NULL;
+        result = false;
         *length = 0;
     }
     return result;
@@ -1848,6 +1932,7 @@
         }
         else
         {
+            transport_data->conn_attempted = true;
             if (transport_data->saved_tls_options != NULL)
             {
                 if (OptionHandler_FeedOptions(transport_data->saved_tls_options, transport_data->xioTransport) != OPTIONHANDLER_OK)
@@ -2047,7 +2132,7 @@
             {
                 result = __FAILURE__;
             }
-                
+
             if (sasToken != NULL)
             {
                 free(sasToken);
@@ -2069,7 +2154,7 @@
         RETRY_ACTION retry_action = RETRY_ACTION_RETRY_LATER;
 
         // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_007: [ IoTHubTransport_MQTT_Common_DoWork shall try to reconnect according to the current retry policy set ]
-        if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_NOT_CONNECTED && transport_data->isRecoverableError && 
+        if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_NOT_CONNECTED && transport_data->isRecoverableError &&
             (retry_control_should_retry(transport_data->retry_control_handle, &retry_action) != 0 || retry_action == RETRY_ACTION_RETRY_NOW))
         {
             // Note: in case retry_control_should_retry fails, the reconnection shall be attempted anyway (defaulting to policy IOTHUB_CLIENT_RETRY_IMMEDIATE).
@@ -2126,14 +2211,9 @@
                 if ((current_time - transport_data->mqtt_connect_time) / 1000 > (transport_data->option_sas_token_lifetime_secs*SAS_REFRESH_MULTIPLIER))
                 {
                     /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_058: [ If the sas token has timed out IoTHubTransport_MQTT_Common_DoWork shall disconnect from the mqtt client and destroy the transport information and wait for reconnect. ] */
-                    OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
-                    set_saved_tls_options(transport_data, options);
-                    (void)mqtt_client_disconnect(transport_data->mqttClient, NULL, NULL);
-                    xio_destroy(transport_data->xioTransport);
-                    transport_data->xioTransport = NULL;
+                    DisconnectFromClient(transport_data);
 
                     IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN);
-                    transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
                     transport_data->currPacketState = UNKNOWN_TYPE;
                     transport_data->device_twin_get_sent = false;
                     if (transport_data->topic_MqttMessage != NULL)
@@ -2208,7 +2288,7 @@
     }
     else
     {
-        memset(state, 0, sizeof(MQTTTRANSPORT_HANDLE_DATA) );
+        memset(state, 0, sizeof(MQTTTRANSPORT_HANDLE_DATA));
         if ((state->msgTickCounter = tickcounter_create()) == NULL)
         {
             LogError("Invalid Argument: iotHubName is empty");
@@ -2242,7 +2322,7 @@
         }
         else
         {
-            if ( (state->topic_MqttEvent = buildMqttEventString(upperConfig->deviceId, moduleId) ) == NULL)
+            if ((state->topic_MqttEvent = buildMqttEventString(upperConfig->deviceId, moduleId)) == NULL)
             {
                 LogError("Could not create topic_MqttEvent for MQTT");
                 free_transport_handle_data(state);
@@ -2262,13 +2342,13 @@
                     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_008: [If the upperConfig contains a valid protocolGatewayHostName value the this shall be used for the hostname, otherwise the hostname shall be constructed using the iothubname and iothubSuffix.] */
                     if (upperConfig->protocolGatewayHostName == NULL)
                     {
-                         state->hostAddress = STRING_construct_sprintf("%s.%s", upperConfig->iotHubName, upperConfig->iotHubSuffix);
+                        state->hostAddress = STRING_construct_sprintf("%s.%s", upperConfig->iotHubName, upperConfig->iotHubSuffix);
                     }
                     else
                     {
                         state->hostAddress = STRING_construct(upperConfig->protocolGatewayHostName);
                     }
-                
+
                     if (state->hostAddress == NULL)
                     {
                         LogError("failure constructing host address.");
@@ -2312,6 +2392,7 @@
                         state->isProductInfoSet = false;
                         state->option_sas_token_lifetime_secs = SAS_TOKEN_DEFAULT_LIFETIME;
                         state->auto_url_encode_decode = false;
+                        state->conn_attempted = false;
                     }
                 }
             }
@@ -2342,12 +2423,12 @@
     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, both deviceKey and deviceSasToken, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_003: [If both deviceKey & deviceSasToken fields are NOT NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
     else if (config->upperConfig == NULL ||
-             config->upperConfig->protocol == NULL || 
-             config->upperConfig->deviceId == NULL || 
-             ((config->upperConfig->deviceKey != NULL) && (config->upperConfig->deviceSasToken != NULL)) ||
-             //is_key_validate(config) != 0 ||
-             config->upperConfig->iotHubName == NULL || 
-             config->upperConfig->iotHubSuffix == NULL)
+        config->upperConfig->protocol == NULL ||
+        config->upperConfig->deviceId == NULL ||
+        ((config->upperConfig->deviceKey != NULL) && (config->upperConfig->deviceSasToken != NULL)) ||
+        //is_key_validate(config) != 0 ||
+        config->upperConfig->iotHubName == NULL ||
+        config->upperConfig->iotHubSuffix == NULL)
     {
         LogError("Invalid Argument: upperConfig structure contains an invalid parameter");
         result = NULL;
@@ -2359,7 +2440,7 @@
         result = NULL;
     }
     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_006: [If the upperConfig's variables deviceId is an empty strings or length is greater then 128 then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
-    else if ( ( (deviceIdSize = strlen(config->upperConfig->deviceId)) > 128U) || (deviceIdSize == 0) )
+    else if (((deviceIdSize = strlen(config->upperConfig->deviceId)) > 128U) || (deviceIdSize == 0))
     {
         LogError("Invalid Argument: DeviceId is of an invalid size");
         result = NULL;
@@ -2463,31 +2544,9 @@
         {
             result = 0;
         }
-        if (result == 0 && transport_data->topic_NotifyState == NULL)
-        {
-            /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_044: [`IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin` shall construct the get state topic string and the notify state topic string.] */
-            transport_data->topic_NotifyState = STRING_construct(TOPIC_NOTIFICATION_STATE);
-            if (transport_data->topic_NotifyState == NULL)
-            {
-                LogError("Failure: unable constructing notify state topic");
-                result = __FAILURE__;
-            }
-            else
-            {
-                /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_047: [On success IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin shall return 0.] */
-                transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
-                result = 0;
-            }
-        }
         if (result == 0)
         {
-            if (transport_data->currPacketState != CONNACK_TYPE &&
-                transport_data->currPacketState != CONNECT_TYPE &&
-                transport_data->currPacketState != DISCONNECT_TYPE &&
-                transport_data->currPacketState != PACKET_TYPE_ERROR)
-            {
-                transport_data->currPacketState = SUBSCRIBE_TYPE;
-            }
+            changeStateToSubscribeIfAllowed(transport_data);
         }
     }
     return result;
@@ -2560,13 +2619,7 @@
         {
             /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_005 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall schedule the send of the subscription.]*/
             /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_007 : [On success IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return 0.]*/
-            if (transport_data->currPacketState != CONNACK_TYPE &&
-                transport_data->currPacketState != CONNECT_TYPE &&
-                transport_data->currPacketState != DISCONNECT_TYPE &&
-                transport_data->currPacketState != PACKET_TYPE_ERROR)
-            {
-                transport_data->currPacketState = SUBSCRIBE_TYPE;
-            }
+            changeStateToSubscribeIfAllowed(transport_data);
         }
     }
     return result;
@@ -2666,7 +2719,7 @@
     else
     {
         /* Code_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransport_MQTT_Common_Subscribe shall set a flag to enable mqtt_client_subscribe to be called to subscribe to the Message Topic.] */
-        transport_data->topic_MqttMessage = buildTopicMqttMessage(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id) );
+        transport_data->topic_MqttMessage = buildTopicMqttMessage(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id));
         if (transport_data->topic_MqttMessage == NULL)
         {
             LogError("Failure constructing Message Topic");
@@ -2676,13 +2729,7 @@
         {
             transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
             /* Code_SRS_IOTHUB_MQTT_TRANSPORT_07_035: [If current packet state is not CONNACT, DISCONNECT_TYPE, or PACKET_TYPE_ERROR then IoTHubTransport_MQTT_Common_Subscribe shall set the packet state to SUBSCRIBE_TYPE.]*/
-            if (transport_data->currPacketState != CONNACK_TYPE &&
-                transport_data->currPacketState != CONNECT_TYPE &&
-                transport_data->currPacketState != DISCONNECT_TYPE &&
-                transport_data->currPacketState != PACKET_TYPE_ERROR)
-            {
-                transport_data->currPacketState = SUBSCRIBE_TYPE;
-            }
+            changeStateToSubscribeIfAllowed(transport_data);
             result = 0;
         }
     }
@@ -2727,7 +2774,8 @@
 
         if (transport_data->currPacketState == PUBLISH_TYPE)
         {
-            if (item_type == IOTHUB_TYPE_DEVICE_TWIN)
+            // Ensure the reported property suback has been received
+            if (item_type == IOTHUB_TYPE_DEVICE_TWIN && transport_data->twin_resp_sub_recv)
             {
                 MQTT_DEVICE_TWIN_ITEM* mqtt_info = (MQTT_DEVICE_TWIN_ITEM*)malloc(sizeof(MQTT_DEVICE_TWIN_ITEM));
                 if (mqtt_info == NULL)
@@ -2741,7 +2789,7 @@
                     mqtt_info->iothub_type = item_type;
                     mqtt_info->iothub_msg_id = iothub_item->device_twin->item_id;
                     mqtt_info->retryCount = 0;
-                    
+
                     /* Codes_SRS_IOTHUBCLIENT_LL_07_005: [ If successful IoTHubTransport_MQTT_Common_ProcessItem shall add mqtt info structure acknowledgement queue. ] */
                     DList_InsertTailList(&transport_data->ack_waiting_queue, &mqtt_info->entry);
 
@@ -2855,10 +2903,12 @@
                         else
                         {
                             size_t messageLength;
-                            const unsigned char* messagePayload = RetrieveMessagePayload(mqttMsgEntry->iotHubMessageEntry->messageHandle, &messageLength);
-                            if (messageLength == 0 || messagePayload == NULL)
+                            const unsigned char* messagePayload = NULL;
+                            if (!RetrieveMessagePayload(mqttMsgEntry->iotHubMessageEntry->messageHandle, &messagePayload, &messageLength))
                             {
                                 LogError("Failure from creating Message IoTHubMessage_GetData");
+                                (void)DList_RemoveEntryList(currentListEntry);
+                                sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
                             }
                             else
                             {
@@ -2884,9 +2934,11 @@
 
                     /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
                     size_t messageLength;
-                    const unsigned char* messagePayload = RetrieveMessagePayload(iothubMsgList->messageHandle, &messageLength);
-                    if (messageLength == 0 || messagePayload == NULL)
+                    const unsigned char* messagePayload = NULL;
+                    if (!RetrieveMessagePayload(iothubMsgList->messageHandle, &messagePayload, &messageLength))
                     {
+                        (void)(DList_RemoveEntryList(currentListEntry));
+                        sendMsgComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
                         LogError("Failure result from IoTHubMessage_GetData");
                     }
                     else
@@ -3108,7 +3160,7 @@
         else
         {
             /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_039: [If the option parameter is set to "x509certificate" then the value shall be a const char of the certificate to be used for x509.] */
-            if ( ((strcmp(OPTION_X509_CERT, option) == 0) || (strcmp(OPTION_X509_PRIVATE_KEY, option) == 0)) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509) )
+            if (((strcmp(OPTION_X509_CERT, option) == 0) || (strcmp(OPTION_X509_PRIVATE_KEY, option) == 0)) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509))
             {
                 IoTHubClient_Auth_Set_x509_Type(transport_data->authorization_module, true);
             }
@@ -3191,12 +3243,12 @@
                 LogError("IoTHubTransport_MQTT_Common_Register: deviceId does not match.");
                 result = NULL;
             }
-            else if (! check_module_ids_equal(STRING_c_str(transport_data->module_id), device->moduleId))
+            else if (!check_module_ids_equal(STRING_c_str(transport_data->module_id), device->moduleId))
             {
                 LogError("IoTHubTransport_MQTT_Common_Register: moduleId does not match.");
                 result = NULL;
             }
-            else if (IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module) == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY && 
+            else if (IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module) == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY &&
                 (strcmp(IoTHubClient_Auth_Get_DeviceKey(transport_data->authorization_module), device->deviceKey) != 0))
             {
                 LogError("IoTHubTransport_MQTT_Common_Register: deviceKey does not match.");
@@ -3306,14 +3358,7 @@
     {
         // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_067: [ IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall set a flag to enable mqtt_client_subscribe to be called to subscribe to the input queue Message Topic.]
         transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
-        if (transport_data->currPacketState != CONNACK_TYPE &&
-            transport_data->currPacketState != CONNECT_TYPE &&
-            transport_data->currPacketState != DISCONNECT_TYPE &&
-            transport_data->currPacketState != PACKET_TYPE_ERROR)
-        {
-            // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_068: [ If current packet state is not CONNACK, DISCONNECT_TYPE, or PACKET_TYPE_ERROR then IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall set the packet state to SUBSCRIBE_TYPE.]
-            transport_data->currPacketState = SUBSCRIBE_TYPE;
-        }
+        changeStateToSubscribeIfAllowed(transport_data);
         // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_070: [ On success IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall return 0.]
         result = 0;
     }
--- a/iothubtransportmqtt.c	Tue Jun 26 19:14:02 2018 -0700
+++ b/iothubtransportmqtt.c	Tue Sep 11 11:12:42 2018 -0700
@@ -117,7 +117,7 @@
 
 static int IoTHubTransportMqtt_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
 {
-    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_25_012: [** IoTHubTransportMqtt_SetRetryPolicy shall call into the IoTHubMqttAbstract_SetRetryPolicy function. ] */ 
+    /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_25_012: [** IoTHubTransportMqtt_SetRetryPolicy shall call into the IoTHubMqttAbstract_SetRetryPolicy function. ] */
     return IoTHubTransport_MQTT_Common_SetRetryPolicy(handle, retryPolicy, retryTimeoutLimitInSeconds);
 }
 
@@ -164,7 +164,7 @@
 }
 
 
-static TRANSPORT_PROVIDER myfunc = 
+static TRANSPORT_PROVIDER myfunc =
 {
     IoTHubTransportMqtt_SendMessageDisposition,     /*pfIotHubTransport_SendMessageDisposition IoTHubTransport_SendMessageDisposition;*/
     IoTHubTransportMqtt_Subscribe_DeviceMethod,     /*pfIoTHubTransport_Subscribe_DeviceMethod IoTHubTransport_Subscribe_DeviceMethod;*/
--- a/iothubtransportmqtt.h	Tue Jun 26 19:14:02 2018 -0700
+++ b/iothubtransportmqtt.h	Tue Sep 11 11:12:42 2018 -0700
@@ -10,7 +10,7 @@
 extern "C"
 {
 #endif
-	extern const TRANSPORT_PROVIDER* MQTT_Protocol(void);
+    extern const TRANSPORT_PROVIDER* MQTT_Protocol(void);
 
 #ifdef __cplusplus
 }