Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

UserRevisionLine numberNew contents of line
XinZhangMS 0:f7f1f0d76dd6 1 // Copyright (c) Microsoft. All rights reserved.
XinZhangMS 0:f7f1f0d76dd6 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
XinZhangMS 0:f7f1f0d76dd6 3
XinZhangMS 0:f7f1f0d76dd6 4 #include <stdlib.h>
XinZhangMS 0:f7f1f0d76dd6 5 #include <ctype.h>
XinZhangMS 0:f7f1f0d76dd6 6 #include "azure_c_shared_utility/optimize_size.h"
XinZhangMS 0:f7f1f0d76dd6 7 #include "azure_c_shared_utility/gballoc.h"
XinZhangMS 0:f7f1f0d76dd6 8
XinZhangMS 0:f7f1f0d76dd6 9 #include "azure_c_shared_utility/xlogging.h"
XinZhangMS 0:f7f1f0d76dd6 10 #include "azure_c_shared_utility/strings.h"
XinZhangMS 0:f7f1f0d76dd6 11 #include "azure_c_shared_utility/doublylinkedlist.h"
XinZhangMS 0:f7f1f0d76dd6 12 #include "azure_c_shared_utility/crt_abstractions.h"
XinZhangMS 0:f7f1f0d76dd6 13 #include "azure_c_shared_utility/agenttime.h"
XinZhangMS 0:f7f1f0d76dd6 14
XinZhangMS 0:f7f1f0d76dd6 15 #include "iothub_client_core_ll.h"
XinZhangMS 0:f7f1f0d76dd6 16 #include "iothub_client_options.h"
XinZhangMS 0:f7f1f0d76dd6 17 #include "internal/iothub_client_private.h"
XinZhangMS 0:f7f1f0d76dd6 18 #include "azure_umqtt_c/mqtt_client.h"
XinZhangMS 0:f7f1f0d76dd6 19 #include "azure_c_shared_utility/sastoken.h"
XinZhangMS 0:f7f1f0d76dd6 20 #include "azure_c_shared_utility/tickcounter.h"
XinZhangMS 0:f7f1f0d76dd6 21
XinZhangMS 0:f7f1f0d76dd6 22 #include "azure_c_shared_utility/tlsio.h"
XinZhangMS 0:f7f1f0d76dd6 23 #include "azure_c_shared_utility/platform.h"
XinZhangMS 0:f7f1f0d76dd6 24
XinZhangMS 0:f7f1f0d76dd6 25 #include "azure_c_shared_utility/string_tokenizer.h"
XinZhangMS 0:f7f1f0d76dd6 26 #include "azure_c_shared_utility/shared_util_options.h"
XinZhangMS 0:f7f1f0d76dd6 27 #include "azure_c_shared_utility/urlencode.h"
XinZhangMS 0:f7f1f0d76dd6 28 #include "iothub_client_version.h"
XinZhangMS 0:f7f1f0d76dd6 29 #include "internal/iothub_client_retry_control.h"
XinZhangMS 0:f7f1f0d76dd6 30
XinZhangMS 0:f7f1f0d76dd6 31 #include "internal/iothubtransport_mqtt_common.h"
XinZhangMS 0:f7f1f0d76dd6 32
XinZhangMS 0:f7f1f0d76dd6 33 #include <stdarg.h>
XinZhangMS 0:f7f1f0d76dd6 34 #include <stdio.h>
XinZhangMS 0:f7f1f0d76dd6 35
XinZhangMS 0:f7f1f0d76dd6 36 #include <limits.h>
XinZhangMS 0:f7f1f0d76dd6 37 #include <inttypes.h>
XinZhangMS 0:f7f1f0d76dd6 38
XinZhangMS 0:f7f1f0d76dd6 39 #define SAS_TOKEN_DEFAULT_LIFETIME 3600
XinZhangMS 0:f7f1f0d76dd6 40 #define SAS_REFRESH_MULTIPLIER .8
XinZhangMS 0:f7f1f0d76dd6 41 #define EPOCH_TIME_T_VALUE 0
XinZhangMS 0:f7f1f0d76dd6 42 #define DEFAULT_MQTT_KEEPALIVE 4*60 // 4 min
XinZhangMS 0:f7f1f0d76dd6 43 #define DEFAULT_CONNACK_TIMEOUT 30 // 30 seconds
XinZhangMS 0:f7f1f0d76dd6 44 #define BUILD_CONFIG_USERNAME 24
XinZhangMS 0:f7f1f0d76dd6 45 #define SAS_TOKEN_DEFAULT_LEN 10
XinZhangMS 0:f7f1f0d76dd6 46 #define RESEND_TIMEOUT_VALUE_MIN 1*60
XinZhangMS 0:f7f1f0d76dd6 47 #define MAX_SEND_RECOUNT_LIMIT 2
XinZhangMS 0:f7f1f0d76dd6 48 #define DEFAULT_CONNECTION_INTERVAL 30
XinZhangMS 0:f7f1f0d76dd6 49 #define FAILED_CONN_BACKOFF_VALUE 5
XinZhangMS 0:f7f1f0d76dd6 50 #define STATUS_CODE_FAILURE_VALUE 500
XinZhangMS 0:f7f1f0d76dd6 51 #define STATUS_CODE_TIMEOUT_VALUE 408
XinZhangMS 0:f7f1f0d76dd6 52
XinZhangMS 0:f7f1f0d76dd6 53 #define DEFAULT_RETRY_POLICY IOTHUB_CLIENT_RETRY_EXPONENTIAL_BACKOFF_WITH_JITTER
XinZhangMS 0:f7f1f0d76dd6 54 #define DEFAULT_RETRY_TIMEOUT_IN_SECONDS 0
XinZhangMS 0:f7f1f0d76dd6 55
XinZhangMS 0:f7f1f0d76dd6 56 static const char TOPIC_DEVICE_TWIN_PREFIX[] = "$iothub/twin";
XinZhangMS 0:f7f1f0d76dd6 57 static const char TOPIC_DEVICE_METHOD_PREFIX[] = "$iothub/methods";
XinZhangMS 0:f7f1f0d76dd6 58
XinZhangMS 0:f7f1f0d76dd6 59 static const char* TOPIC_GET_DESIRED_STATE = "$iothub/twin/res/#";
XinZhangMS 0:f7f1f0d76dd6 60 static const char* TOPIC_NOTIFICATION_STATE = "$iothub/twin/PATCH/properties/desired/#";
XinZhangMS 0:f7f1f0d76dd6 61
XinZhangMS 0:f7f1f0d76dd6 62 static const char* TOPIC_DEVICE_MSG = "devices/%s/messages/devicebound/#";
XinZhangMS 0:f7f1f0d76dd6 63 static const char* TOPIC_DEVICE_MODULE_MSG = "devices/%s/modules/%s/messages/devicebound/#";
XinZhangMS 0:f7f1f0d76dd6 64 static const char* TOPIC_DEVICE_DEVICE = "devices/%s/messages/events/";
XinZhangMS 0:f7f1f0d76dd6 65 static const char* TOPIC_DEVICE_DEVICE_MODULE = "devices/%s/modules/%s/messages/events/";
XinZhangMS 0:f7f1f0d76dd6 66
XinZhangMS 0:f7f1f0d76dd6 67 static const char* TOPIC_INPUT_QUEUE_NAME = "devices/%s/modules/%s/#";
XinZhangMS 0:f7f1f0d76dd6 68
XinZhangMS 0:f7f1f0d76dd6 69 static const char* TOPIC_DEVICE_METHOD_SUBSCRIBE = "$iothub/methods/POST/#";
XinZhangMS 0:f7f1f0d76dd6 70
XinZhangMS 0:f7f1f0d76dd6 71 static const char* IOTHUB_API_VERSION = "2017-11-08-preview";
XinZhangMS 0:f7f1f0d76dd6 72
XinZhangMS 0:f7f1f0d76dd6 73 static const char* PROPERTY_SEPARATOR = "&";
XinZhangMS 0:f7f1f0d76dd6 74 static const char* REPORTED_PROPERTIES_TOPIC = "$iothub/twin/PATCH/properties/reported/?$rid=%"PRIu16;
XinZhangMS 0:f7f1f0d76dd6 75 static const char* GET_PROPERTIES_TOPIC = "$iothub/twin/GET/?$rid=%"PRIu16;
XinZhangMS 0:f7f1f0d76dd6 76 static const char* DEVICE_METHOD_RESPONSE_TOPIC = "$iothub/methods/res/%d/?$rid=%s";
XinZhangMS 0:f7f1f0d76dd6 77
XinZhangMS 0:f7f1f0d76dd6 78 static const char* REQUEST_ID_PROPERTY = "?$rid=";
XinZhangMS 0:f7f1f0d76dd6 79
XinZhangMS 0:f7f1f0d76dd6 80 static const char* MESSAGE_ID_PROPERTY = "mid";
XinZhangMS 0:f7f1f0d76dd6 81 static const char* CORRELATION_ID_PROPERTY = "cid";
XinZhangMS 0:f7f1f0d76dd6 82 static const char* CONTENT_TYPE_PROPERTY = "ct";
XinZhangMS 0:f7f1f0d76dd6 83 static const char* CONTENT_ENCODING_PROPERTY = "ce";
XinZhangMS 0:f7f1f0d76dd6 84 static const char* DIAGNOSTIC_ID_PROPERTY = "diagid";
XinZhangMS 0:f7f1f0d76dd6 85 static const char* DIAGNOSTIC_CONTEXT_PROPERTY = "diagctx";
XinZhangMS 0:f7f1f0d76dd6 86 static const char* CONNECTION_DEVICE_ID = "cdid";
XinZhangMS 0:f7f1f0d76dd6 87 static const char* CONNECTION_MODULE_ID_PROPERTY = "cmid";
XinZhangMS 0:f7f1f0d76dd6 88
XinZhangMS 0:f7f1f0d76dd6 89
XinZhangMS 0:f7f1f0d76dd6 90 static const char* DIAGNOSTIC_CONTEXT_CREATION_TIME_UTC_PROPERTY = "creationtimeutc";
XinZhangMS 0:f7f1f0d76dd6 91
XinZhangMS 0:f7f1f0d76dd6 92 #define UNSUBSCRIBE_FROM_TOPIC 0x0000
XinZhangMS 0:f7f1f0d76dd6 93 #define SUBSCRIBE_GET_REPORTED_STATE_TOPIC 0x0001
XinZhangMS 0:f7f1f0d76dd6 94 #define SUBSCRIBE_NOTIFICATION_STATE_TOPIC 0x0002
XinZhangMS 0:f7f1f0d76dd6 95 #define SUBSCRIBE_TELEMETRY_TOPIC 0x0004
XinZhangMS 0:f7f1f0d76dd6 96 #define SUBSCRIBE_METHODS_TOPIC 0x0008
XinZhangMS 0:f7f1f0d76dd6 97 #define SUBSCRIBE_DEVICE_METHOD_TOPIC 0x0010
XinZhangMS 0:f7f1f0d76dd6 98 #define SUBSCRIBE_INPUT_QUEUE_TOPIC 0x0020
XinZhangMS 0:f7f1f0d76dd6 99 #define SUBSCRIBE_TOPIC_COUNT 5
XinZhangMS 0:f7f1f0d76dd6 100
XinZhangMS 0:f7f1f0d76dd6 101 DEFINE_ENUM_STRINGS(MQTT_CLIENT_EVENT_ERROR, MQTT_CLIENT_EVENT_ERROR_VALUES)
XinZhangMS 0:f7f1f0d76dd6 102
XinZhangMS 0:f7f1f0d76dd6 103 typedef struct SYSTEM_PROPERTY_INFO_TAG
XinZhangMS 0:f7f1f0d76dd6 104 {
XinZhangMS 0:f7f1f0d76dd6 105 const char* propName;
XinZhangMS 0:f7f1f0d76dd6 106 size_t propLength;
XinZhangMS 0:f7f1f0d76dd6 107 } SYSTEM_PROPERTY_INFO;
XinZhangMS 0:f7f1f0d76dd6 108
XinZhangMS 0:f7f1f0d76dd6 109 static SYSTEM_PROPERTY_INFO sysPropList[] = {
XinZhangMS 0:f7f1f0d76dd6 110 { "%24.exp", 7 },
XinZhangMS 0:f7f1f0d76dd6 111 { "%24.mid", 7 },
XinZhangMS 0:f7f1f0d76dd6 112 { "%24.uid", 7 },
XinZhangMS 0:f7f1f0d76dd6 113 { "%24.to", 6 },
XinZhangMS 0:f7f1f0d76dd6 114 { "%24.cid", 7 },
XinZhangMS 0:f7f1f0d76dd6 115 { "%24.ct", 6 },
XinZhangMS 0:f7f1f0d76dd6 116 { "%24.ce", 6 },
XinZhangMS 0:f7f1f0d76dd6 117 { "devices/", 8 },
XinZhangMS 0:f7f1f0d76dd6 118 { "iothub-operation", 16 },
XinZhangMS 0:f7f1f0d76dd6 119 { "iothub-ack", 10 },
XinZhangMS 0:f7f1f0d76dd6 120 { "%24.on", 6 },
XinZhangMS 0:f7f1f0d76dd6 121 { "%24.cdid", 8 },
XinZhangMS 0:f7f1f0d76dd6 122 { "%24.cmid", 8 }
XinZhangMS 0:f7f1f0d76dd6 123 };
XinZhangMS 0:f7f1f0d76dd6 124
XinZhangMS 0:f7f1f0d76dd6 125 static const int slashes_to_reach_input_name = 5;
XinZhangMS 0:f7f1f0d76dd6 126
XinZhangMS 0:f7f1f0d76dd6 127 typedef enum DEVICE_TWIN_MSG_TYPE_TAG
XinZhangMS 0:f7f1f0d76dd6 128 {
XinZhangMS 0:f7f1f0d76dd6 129 REPORTED_STATE,
XinZhangMS 0:f7f1f0d76dd6 130 RETRIEVE_PROPERTIES
XinZhangMS 0:f7f1f0d76dd6 131 } DEVICE_TWIN_MSG_TYPE;
XinZhangMS 0:f7f1f0d76dd6 132
XinZhangMS 0:f7f1f0d76dd6 133 typedef enum MQTT_TRANSPORT_CREDENTIAL_TYPE_TAG
XinZhangMS 0:f7f1f0d76dd6 134 {
XinZhangMS 0:f7f1f0d76dd6 135 CREDENTIAL_NOT_BUILD,
XinZhangMS 0:f7f1f0d76dd6 136 X509,
XinZhangMS 0:f7f1f0d76dd6 137 SAS_TOKEN_FROM_USER,
XinZhangMS 0:f7f1f0d76dd6 138 DEVICE_KEY,
XinZhangMS 0:f7f1f0d76dd6 139 } MQTT_TRANSPORT_CREDENTIAL_TYPE;
XinZhangMS 0:f7f1f0d76dd6 140
XinZhangMS 0:f7f1f0d76dd6 141 typedef enum MQTT_CLIENT_STATUS_TAG
XinZhangMS 0:f7f1f0d76dd6 142 {
XinZhangMS 0:f7f1f0d76dd6 143 MQTT_CLIENT_STATUS_NOT_CONNECTED,
XinZhangMS 0:f7f1f0d76dd6 144 MQTT_CLIENT_STATUS_CONNECTING,
XinZhangMS 0:f7f1f0d76dd6 145 MQTT_CLIENT_STATUS_CONNECTED,
XinZhangMS 0:f7f1f0d76dd6 146 MQTT_CLIENT_STATUS_PENDING_CLOSE
XinZhangMS 0:f7f1f0d76dd6 147 } MQTT_CLIENT_STATUS;
XinZhangMS 0:f7f1f0d76dd6 148
XinZhangMS 0:f7f1f0d76dd6 149 typedef struct MQTTTRANSPORT_HANDLE_DATA_TAG
XinZhangMS 0:f7f1f0d76dd6 150 {
XinZhangMS 0:f7f1f0d76dd6 151 // Topic control
XinZhangMS 0:f7f1f0d76dd6 152 STRING_HANDLE topic_MqttEvent;
XinZhangMS 0:f7f1f0d76dd6 153 STRING_HANDLE topic_MqttMessage;
XinZhangMS 0:f7f1f0d76dd6 154 STRING_HANDLE topic_GetState;
XinZhangMS 0:f7f1f0d76dd6 155 STRING_HANDLE topic_NotifyState;
XinZhangMS 0:f7f1f0d76dd6 156 STRING_HANDLE topic_InputQueue;
XinZhangMS 0:f7f1f0d76dd6 157
XinZhangMS 0:f7f1f0d76dd6 158 STRING_HANDLE topic_DeviceMethods;
XinZhangMS 0:f7f1f0d76dd6 159
XinZhangMS 0:f7f1f0d76dd6 160 uint32_t topics_ToSubscribe;
XinZhangMS 0:f7f1f0d76dd6 161
XinZhangMS 0:f7f1f0d76dd6 162 // Connection related constants
XinZhangMS 0:f7f1f0d76dd6 163 STRING_HANDLE hostAddress;
XinZhangMS 0:f7f1f0d76dd6 164 STRING_HANDLE device_id;
XinZhangMS 0:f7f1f0d76dd6 165 STRING_HANDLE module_id;
XinZhangMS 0:f7f1f0d76dd6 166 STRING_HANDLE devicesAndModulesPath;
XinZhangMS 0:f7f1f0d76dd6 167 int portNum;
XinZhangMS 0:f7f1f0d76dd6 168 bool conn_attempted;
XinZhangMS 0:f7f1f0d76dd6 169
XinZhangMS 0:f7f1f0d76dd6 170 MQTT_GET_IO_TRANSPORT get_io_transport;
XinZhangMS 0:f7f1f0d76dd6 171
XinZhangMS 0:f7f1f0d76dd6 172 // The current mqtt iothub implementation requires that the hub name and the domain suffix be passed as the first of a series of segments
XinZhangMS 0:f7f1f0d76dd6 173 // passed through the username portion of the connection frame.
XinZhangMS 0:f7f1f0d76dd6 174 // The second segment will contain the device id. The two segments are delemited by a "/".
XinZhangMS 0:f7f1f0d76dd6 175 // The first segment can be a maximum 256 characters.
XinZhangMS 0:f7f1f0d76dd6 176 // The second segment can be a maximum 128 characters.
XinZhangMS 0:f7f1f0d76dd6 177 // With the / delimeter you have 384 chars (Plus a terminator of 0).
XinZhangMS 0:f7f1f0d76dd6 178 STRING_HANDLE configPassedThroughUsername;
XinZhangMS 0:f7f1f0d76dd6 179
XinZhangMS 0:f7f1f0d76dd6 180 // Upper layer
XinZhangMS 0:f7f1f0d76dd6 181 IOTHUB_CLIENT_CORE_LL_HANDLE llClientHandle;
XinZhangMS 0:f7f1f0d76dd6 182
XinZhangMS 0:f7f1f0d76dd6 183 // Protocol
XinZhangMS 0:f7f1f0d76dd6 184 MQTT_CLIENT_HANDLE mqttClient;
XinZhangMS 0:f7f1f0d76dd6 185 XIO_HANDLE xioTransport;
XinZhangMS 0:f7f1f0d76dd6 186
XinZhangMS 0:f7f1f0d76dd6 187 // Session - connection
XinZhangMS 0:f7f1f0d76dd6 188 uint16_t packetId;
XinZhangMS 0:f7f1f0d76dd6 189
XinZhangMS 0:f7f1f0d76dd6 190 // Connection state control
XinZhangMS 0:f7f1f0d76dd6 191 bool isRegistered;
XinZhangMS 0:f7f1f0d76dd6 192 MQTT_CLIENT_STATUS mqttClientStatus;
XinZhangMS 0:f7f1f0d76dd6 193 bool isDestroyCalled;
XinZhangMS 0:f7f1f0d76dd6 194 bool device_twin_get_sent;
XinZhangMS 0:f7f1f0d76dd6 195 bool isRecoverableError;
XinZhangMS 0:f7f1f0d76dd6 196 uint16_t keepAliveValue;
XinZhangMS 0:f7f1f0d76dd6 197 uint16_t connect_timeout_in_sec;
XinZhangMS 0:f7f1f0d76dd6 198 tickcounter_ms_t mqtt_connect_time;
XinZhangMS 0:f7f1f0d76dd6 199 size_t connectFailCount;
XinZhangMS 0:f7f1f0d76dd6 200 tickcounter_ms_t connectTick;
XinZhangMS 0:f7f1f0d76dd6 201 bool log_trace;
XinZhangMS 0:f7f1f0d76dd6 202 bool raw_trace;
XinZhangMS 0:f7f1f0d76dd6 203 TICK_COUNTER_HANDLE msgTickCounter;
XinZhangMS 0:f7f1f0d76dd6 204 OPTIONHANDLER_HANDLE saved_tls_options; // Here are the options from the xio layer if any is saved.
XinZhangMS 0:f7f1f0d76dd6 205 size_t option_sas_token_lifetime_secs;
XinZhangMS 0:f7f1f0d76dd6 206
XinZhangMS 0:f7f1f0d76dd6 207 // Internal lists for message tracking
XinZhangMS 0:f7f1f0d76dd6 208 PDLIST_ENTRY waitingToSend;
XinZhangMS 0:f7f1f0d76dd6 209 DLIST_ENTRY ack_waiting_queue;
XinZhangMS 0:f7f1f0d76dd6 210
XinZhangMS 0:f7f1f0d76dd6 211 // Message tracking
XinZhangMS 0:f7f1f0d76dd6 212 CONTROL_PACKET_TYPE currPacketState;
XinZhangMS 0:f7f1f0d76dd6 213
XinZhangMS 0:f7f1f0d76dd6 214 // Telemetry specific
XinZhangMS 0:f7f1f0d76dd6 215 DLIST_ENTRY telemetry_waitingForAck;
XinZhangMS 0:f7f1f0d76dd6 216 bool auto_url_encode_decode;
XinZhangMS 0:f7f1f0d76dd6 217
XinZhangMS 0:f7f1f0d76dd6 218 // Controls frequency of reconnection logic.
XinZhangMS 0:f7f1f0d76dd6 219 RETRY_CONTROL_HANDLE retry_control_handle;
XinZhangMS 0:f7f1f0d76dd6 220
XinZhangMS 0:f7f1f0d76dd6 221 // Auth module used to generating handle authorization
XinZhangMS 0:f7f1f0d76dd6 222 // with either SAS Token, x509 Certs, and Device SAS Token
XinZhangMS 0:f7f1f0d76dd6 223 IOTHUB_AUTHORIZATION_HANDLE authorization_module;
XinZhangMS 0:f7f1f0d76dd6 224
XinZhangMS 0:f7f1f0d76dd6 225 char* http_proxy_hostname;
XinZhangMS 0:f7f1f0d76dd6 226 int http_proxy_port;
XinZhangMS 0:f7f1f0d76dd6 227 char* http_proxy_username;
XinZhangMS 0:f7f1f0d76dd6 228 char* http_proxy_password;
XinZhangMS 0:f7f1f0d76dd6 229 bool isProductInfoSet;
XinZhangMS 0:f7f1f0d76dd6 230 } MQTTTRANSPORT_HANDLE_DATA, *PMQTTTRANSPORT_HANDLE_DATA;
XinZhangMS 0:f7f1f0d76dd6 231
XinZhangMS 0:f7f1f0d76dd6 232 typedef struct MQTT_DEVICE_TWIN_ITEM_TAG
XinZhangMS 0:f7f1f0d76dd6 233 {
XinZhangMS 0:f7f1f0d76dd6 234 tickcounter_ms_t msgPublishTime;
XinZhangMS 0:f7f1f0d76dd6 235 size_t retryCount;
XinZhangMS 0:f7f1f0d76dd6 236 IOTHUB_IDENTITY_TYPE iothub_type;
XinZhangMS 0:f7f1f0d76dd6 237 uint16_t packet_id;
XinZhangMS 0:f7f1f0d76dd6 238 uint32_t iothub_msg_id;
XinZhangMS 0:f7f1f0d76dd6 239 IOTHUB_DEVICE_TWIN* device_twin_data;
XinZhangMS 0:f7f1f0d76dd6 240 DEVICE_TWIN_MSG_TYPE device_twin_msg_type;
XinZhangMS 0:f7f1f0d76dd6 241 DLIST_ENTRY entry;
XinZhangMS 0:f7f1f0d76dd6 242 } MQTT_DEVICE_TWIN_ITEM;
XinZhangMS 0:f7f1f0d76dd6 243
XinZhangMS 0:f7f1f0d76dd6 244 typedef struct MQTT_MESSAGE_DETAILS_LIST_TAG
XinZhangMS 0:f7f1f0d76dd6 245 {
XinZhangMS 0:f7f1f0d76dd6 246 tickcounter_ms_t msgPublishTime;
XinZhangMS 0:f7f1f0d76dd6 247 size_t retryCount;
XinZhangMS 0:f7f1f0d76dd6 248 IOTHUB_MESSAGE_LIST* iotHubMessageEntry;
XinZhangMS 0:f7f1f0d76dd6 249 void* context;
XinZhangMS 0:f7f1f0d76dd6 250 uint16_t packet_id;
XinZhangMS 0:f7f1f0d76dd6 251 DLIST_ENTRY entry;
XinZhangMS 0:f7f1f0d76dd6 252 } MQTT_MESSAGE_DETAILS_LIST, *PMQTT_MESSAGE_DETAILS_LIST;
XinZhangMS 0:f7f1f0d76dd6 253
XinZhangMS 0:f7f1f0d76dd6 254 typedef struct DEVICE_METHOD_INFO_TAG
XinZhangMS 0:f7f1f0d76dd6 255 {
XinZhangMS 0:f7f1f0d76dd6 256 STRING_HANDLE request_id;
XinZhangMS 0:f7f1f0d76dd6 257 } DEVICE_METHOD_INFO;
XinZhangMS 0:f7f1f0d76dd6 258
XinZhangMS 0:f7f1f0d76dd6 259 static void free_proxy_data(MQTTTRANSPORT_HANDLE_DATA* mqtt_transport_instance)
XinZhangMS 0:f7f1f0d76dd6 260 {
XinZhangMS 0:f7f1f0d76dd6 261 if (mqtt_transport_instance->http_proxy_hostname != NULL)
XinZhangMS 0:f7f1f0d76dd6 262 {
XinZhangMS 0:f7f1f0d76dd6 263 free(mqtt_transport_instance->http_proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 264 mqtt_transport_instance->http_proxy_hostname = NULL;
XinZhangMS 0:f7f1f0d76dd6 265 }
XinZhangMS 0:f7f1f0d76dd6 266
XinZhangMS 0:f7f1f0d76dd6 267 if (mqtt_transport_instance->http_proxy_username != NULL)
XinZhangMS 0:f7f1f0d76dd6 268 {
XinZhangMS 0:f7f1f0d76dd6 269 free(mqtt_transport_instance->http_proxy_username);
XinZhangMS 0:f7f1f0d76dd6 270 mqtt_transport_instance->http_proxy_username = NULL;
XinZhangMS 0:f7f1f0d76dd6 271 }
XinZhangMS 0:f7f1f0d76dd6 272
XinZhangMS 0:f7f1f0d76dd6 273 if (mqtt_transport_instance->http_proxy_password != NULL)
XinZhangMS 0:f7f1f0d76dd6 274 {
XinZhangMS 0:f7f1f0d76dd6 275 free(mqtt_transport_instance->http_proxy_password);
XinZhangMS 0:f7f1f0d76dd6 276 mqtt_transport_instance->http_proxy_password = NULL;
XinZhangMS 0:f7f1f0d76dd6 277 }
XinZhangMS 0:f7f1f0d76dd6 278 }
XinZhangMS 0:f7f1f0d76dd6 279
XinZhangMS 0:f7f1f0d76dd6 280 static void set_saved_tls_options(PMQTTTRANSPORT_HANDLE_DATA transport, OPTIONHANDLER_HANDLE new_options)
XinZhangMS 0:f7f1f0d76dd6 281 {
XinZhangMS 0:f7f1f0d76dd6 282 if (transport->saved_tls_options != NULL)
XinZhangMS 0:f7f1f0d76dd6 283 {
XinZhangMS 0:f7f1f0d76dd6 284 OptionHandler_Destroy(transport->saved_tls_options);
XinZhangMS 0:f7f1f0d76dd6 285 }
XinZhangMS 0:f7f1f0d76dd6 286 transport->saved_tls_options = new_options;
XinZhangMS 0:f7f1f0d76dd6 287 }
XinZhangMS 0:f7f1f0d76dd6 288
XinZhangMS 0:f7f1f0d76dd6 289 static void free_transport_handle_data(MQTTTRANSPORT_HANDLE_DATA* transport_data)
XinZhangMS 0:f7f1f0d76dd6 290 {
XinZhangMS 0:f7f1f0d76dd6 291 if (transport_data->mqttClient != NULL)
XinZhangMS 0:f7f1f0d76dd6 292 {
XinZhangMS 0:f7f1f0d76dd6 293 mqtt_client_deinit(transport_data->mqttClient);
XinZhangMS 0:f7f1f0d76dd6 294 }
XinZhangMS 0:f7f1f0d76dd6 295
XinZhangMS 0:f7f1f0d76dd6 296 if (transport_data->retry_control_handle != NULL)
XinZhangMS 0:f7f1f0d76dd6 297 {
XinZhangMS 0:f7f1f0d76dd6 298 retry_control_destroy(transport_data->retry_control_handle);
XinZhangMS 0:f7f1f0d76dd6 299 }
XinZhangMS 0:f7f1f0d76dd6 300
XinZhangMS 0:f7f1f0d76dd6 301 set_saved_tls_options(transport_data, NULL);
XinZhangMS 0:f7f1f0d76dd6 302
XinZhangMS 0:f7f1f0d76dd6 303 tickcounter_destroy(transport_data->msgTickCounter);
XinZhangMS 0:f7f1f0d76dd6 304
XinZhangMS 0:f7f1f0d76dd6 305 free_proxy_data(transport_data);
XinZhangMS 0:f7f1f0d76dd6 306
XinZhangMS 0:f7f1f0d76dd6 307 STRING_delete(transport_data->devicesAndModulesPath);
XinZhangMS 0:f7f1f0d76dd6 308 STRING_delete(transport_data->topic_MqttEvent);
XinZhangMS 0:f7f1f0d76dd6 309 STRING_delete(transport_data->topic_MqttMessage);
XinZhangMS 0:f7f1f0d76dd6 310 STRING_delete(transport_data->device_id);
XinZhangMS 0:f7f1f0d76dd6 311 STRING_delete(transport_data->module_id);
XinZhangMS 0:f7f1f0d76dd6 312 STRING_delete(transport_data->hostAddress);
XinZhangMS 0:f7f1f0d76dd6 313 STRING_delete(transport_data->configPassedThroughUsername);
XinZhangMS 0:f7f1f0d76dd6 314 STRING_delete(transport_data->topic_GetState);
XinZhangMS 0:f7f1f0d76dd6 315 STRING_delete(transport_data->topic_NotifyState);
XinZhangMS 0:f7f1f0d76dd6 316 STRING_delete(transport_data->topic_DeviceMethods);
XinZhangMS 0:f7f1f0d76dd6 317 STRING_delete(transport_data->topic_InputQueue);
XinZhangMS 0:f7f1f0d76dd6 318
XinZhangMS 0:f7f1f0d76dd6 319 free(transport_data);
XinZhangMS 0:f7f1f0d76dd6 320 }
XinZhangMS 0:f7f1f0d76dd6 321
XinZhangMS 0:f7f1f0d76dd6 322 int IoTHubTransport_MQTT_Common_SetRetryPolicy(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_RETRY_POLICY retryPolicy, size_t retryTimeoutLimitInSeconds)
XinZhangMS 0:f7f1f0d76dd6 323 {
XinZhangMS 0:f7f1f0d76dd6 324 int result;
XinZhangMS 0:f7f1f0d76dd6 325
XinZhangMS 0:f7f1f0d76dd6 326 if (handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 327 {
XinZhangMS 0:f7f1f0d76dd6 328 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_041: [**If any handle is NULL then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return resultant line.] */
XinZhangMS 0:f7f1f0d76dd6 329 LogError("Invalid handle parameter. NULL.");
XinZhangMS 0:f7f1f0d76dd6 330 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 331 }
XinZhangMS 0:f7f1f0d76dd6 332 else
XinZhangMS 0:f7f1f0d76dd6 333 {
XinZhangMS 0:f7f1f0d76dd6 334 RETRY_CONTROL_HANDLE new_retry_control_handle;
XinZhangMS 0:f7f1f0d76dd6 335
XinZhangMS 0:f7f1f0d76dd6 336 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_006: [ IoTHubTransport_MQTT_Common_SetRetryPolicy shall set the retry logic by calling retry_control_create() with retry policy and retryTimeout as parameters]
XinZhangMS 0:f7f1f0d76dd6 337 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_009: [ If retry_control_create() fails then IoTHubTransport_MQTT_Common_SetRetryPolicy shall revert to previous retry policy and return non-zero value ]
XinZhangMS 0:f7f1f0d76dd6 338 if ((new_retry_control_handle = retry_control_create(retryPolicy, (unsigned int)retryTimeoutLimitInSeconds)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 339 {
XinZhangMS 0:f7f1f0d76dd6 340 LogError("Failed creating new retry control handle");
XinZhangMS 0:f7f1f0d76dd6 341 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 342 }
XinZhangMS 0:f7f1f0d76dd6 343 else
XinZhangMS 0:f7f1f0d76dd6 344 {
XinZhangMS 0:f7f1f0d76dd6 345 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 346 RETRY_CONTROL_HANDLE previous_retry_control_handle = transport_data->retry_control_handle;
XinZhangMS 0:f7f1f0d76dd6 347
XinZhangMS 0:f7f1f0d76dd6 348 transport_data->retry_control_handle = new_retry_control_handle;
XinZhangMS 0:f7f1f0d76dd6 349 retry_control_destroy(previous_retry_control_handle);
XinZhangMS 0:f7f1f0d76dd6 350
XinZhangMS 0:f7f1f0d76dd6 351 /*Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_25_045: [**If retry logic for specified parameters of retry policy and retryTimeoutLimitInSeconds is created successfully then IoTHubTransport_MQTT_Common_SetRetryPolicy shall return 0]*/
XinZhangMS 0:f7f1f0d76dd6 352 result = 0;
XinZhangMS 0:f7f1f0d76dd6 353 }
XinZhangMS 0:f7f1f0d76dd6 354 }
XinZhangMS 0:f7f1f0d76dd6 355
XinZhangMS 0:f7f1f0d76dd6 356 return result;
XinZhangMS 0:f7f1f0d76dd6 357 }
XinZhangMS 0:f7f1f0d76dd6 358
XinZhangMS 0:f7f1f0d76dd6 359 static uint16_t get_next_packet_id(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 360 {
XinZhangMS 0:f7f1f0d76dd6 361 if (transport_data->packetId + 1 >= USHRT_MAX)
XinZhangMS 0:f7f1f0d76dd6 362 {
XinZhangMS 0:f7f1f0d76dd6 363 transport_data->packetId = 1;
XinZhangMS 0:f7f1f0d76dd6 364 }
XinZhangMS 0:f7f1f0d76dd6 365 else
XinZhangMS 0:f7f1f0d76dd6 366 {
XinZhangMS 0:f7f1f0d76dd6 367 transport_data->packetId++;
XinZhangMS 0:f7f1f0d76dd6 368 }
XinZhangMS 0:f7f1f0d76dd6 369 return transport_data->packetId;
XinZhangMS 0:f7f1f0d76dd6 370 }
XinZhangMS 0:f7f1f0d76dd6 371
XinZhangMS 0:f7f1f0d76dd6 372 static const char* retrieve_mqtt_return_codes(CONNECT_RETURN_CODE rtn_code)
XinZhangMS 0:f7f1f0d76dd6 373 {
XinZhangMS 0:f7f1f0d76dd6 374 switch (rtn_code)
XinZhangMS 0:f7f1f0d76dd6 375 {
XinZhangMS 0:f7f1f0d76dd6 376 case CONNECTION_ACCEPTED:
XinZhangMS 0:f7f1f0d76dd6 377 return "Accepted";
XinZhangMS 0:f7f1f0d76dd6 378 case CONN_REFUSED_UNACCEPTABLE_VERSION:
XinZhangMS 0:f7f1f0d76dd6 379 return "Unacceptable Version";
XinZhangMS 0:f7f1f0d76dd6 380 case CONN_REFUSED_ID_REJECTED:
XinZhangMS 0:f7f1f0d76dd6 381 return "Id Rejected";
XinZhangMS 0:f7f1f0d76dd6 382 case CONN_REFUSED_SERVER_UNAVAIL:
XinZhangMS 0:f7f1f0d76dd6 383 return "Server Unavailable";
XinZhangMS 0:f7f1f0d76dd6 384 case CONN_REFUSED_BAD_USERNAME_PASSWORD:
XinZhangMS 0:f7f1f0d76dd6 385 return "Bad Username/Password";
XinZhangMS 0:f7f1f0d76dd6 386 case CONN_REFUSED_NOT_AUTHORIZED:
XinZhangMS 0:f7f1f0d76dd6 387 return "Not Authorized";
XinZhangMS 0:f7f1f0d76dd6 388 case CONN_REFUSED_UNKNOWN:
XinZhangMS 0:f7f1f0d76dd6 389 default:
XinZhangMS 0:f7f1f0d76dd6 390 return "Unknown";
XinZhangMS 0:f7f1f0d76dd6 391 }
XinZhangMS 0:f7f1f0d76dd6 392 }
XinZhangMS 0:f7f1f0d76dd6 393
XinZhangMS 0:f7f1f0d76dd6 394 static int retrieve_device_method_rid_info(const char* resp_topic, STRING_HANDLE method_name, STRING_HANDLE request_id)
XinZhangMS 0:f7f1f0d76dd6 395 {
XinZhangMS 0:f7f1f0d76dd6 396 int result;
XinZhangMS 0:f7f1f0d76dd6 397 STRING_TOKENIZER_HANDLE token_handle = STRING_TOKENIZER_create_from_char(resp_topic);
XinZhangMS 0:f7f1f0d76dd6 398 if (token_handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 399 {
XinZhangMS 0:f7f1f0d76dd6 400 LogError("Failed creating token from device twin topic.");
XinZhangMS 0:f7f1f0d76dd6 401 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 402 }
XinZhangMS 0:f7f1f0d76dd6 403 else
XinZhangMS 0:f7f1f0d76dd6 404 {
XinZhangMS 0:f7f1f0d76dd6 405 STRING_HANDLE token_value;
XinZhangMS 0:f7f1f0d76dd6 406 if ((token_value = STRING_new()) == NULL)
XinZhangMS 0:f7f1f0d76dd6 407 {
XinZhangMS 0:f7f1f0d76dd6 408 LogError("Failed allocating new string .");
XinZhangMS 0:f7f1f0d76dd6 409 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 410 }
XinZhangMS 0:f7f1f0d76dd6 411 else
XinZhangMS 0:f7f1f0d76dd6 412 {
XinZhangMS 0:f7f1f0d76dd6 413 size_t token_index = 0;
XinZhangMS 0:f7f1f0d76dd6 414 size_t request_id_length = strlen(REQUEST_ID_PROPERTY);
XinZhangMS 0:f7f1f0d76dd6 415 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 416 while (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/") == 0)
XinZhangMS 0:f7f1f0d76dd6 417 {
XinZhangMS 0:f7f1f0d76dd6 418 if (token_index == 3)
XinZhangMS 0:f7f1f0d76dd6 419 {
XinZhangMS 0:f7f1f0d76dd6 420 if (STRING_concat_with_STRING(method_name, token_value) != 0)
XinZhangMS 0:f7f1f0d76dd6 421 {
XinZhangMS 0:f7f1f0d76dd6 422 LogError("Failed STRING_concat_with_STRING.");
XinZhangMS 0:f7f1f0d76dd6 423 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 424 break;
XinZhangMS 0:f7f1f0d76dd6 425 }
XinZhangMS 0:f7f1f0d76dd6 426 }
XinZhangMS 0:f7f1f0d76dd6 427 else if (token_index == 4)
XinZhangMS 0:f7f1f0d76dd6 428 {
XinZhangMS 0:f7f1f0d76dd6 429 if (STRING_length(token_value) >= request_id_length)
XinZhangMS 0:f7f1f0d76dd6 430 {
XinZhangMS 0:f7f1f0d76dd6 431 const char* request_id_value = STRING_c_str(token_value);
XinZhangMS 0:f7f1f0d76dd6 432 if (memcmp(request_id_value, REQUEST_ID_PROPERTY, request_id_length) == 0)
XinZhangMS 0:f7f1f0d76dd6 433 {
XinZhangMS 0:f7f1f0d76dd6 434 if (STRING_concat(request_id, request_id_value + request_id_length) != 0)
XinZhangMS 0:f7f1f0d76dd6 435 {
XinZhangMS 0:f7f1f0d76dd6 436 LogError("Failed STRING_concat failed.");
XinZhangMS 0:f7f1f0d76dd6 437 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 438 }
XinZhangMS 0:f7f1f0d76dd6 439 else
XinZhangMS 0:f7f1f0d76dd6 440 {
XinZhangMS 0:f7f1f0d76dd6 441 result = 0;
XinZhangMS 0:f7f1f0d76dd6 442 }
XinZhangMS 0:f7f1f0d76dd6 443 break;
XinZhangMS 0:f7f1f0d76dd6 444 }
XinZhangMS 0:f7f1f0d76dd6 445 }
XinZhangMS 0:f7f1f0d76dd6 446 }
XinZhangMS 0:f7f1f0d76dd6 447 token_index++;
XinZhangMS 0:f7f1f0d76dd6 448 }
XinZhangMS 0:f7f1f0d76dd6 449 STRING_delete(token_value);
XinZhangMS 0:f7f1f0d76dd6 450 }
XinZhangMS 0:f7f1f0d76dd6 451 STRING_TOKENIZER_destroy(token_handle);
XinZhangMS 0:f7f1f0d76dd6 452 }
XinZhangMS 0:f7f1f0d76dd6 453 return result;
XinZhangMS 0:f7f1f0d76dd6 454 }
XinZhangMS 0:f7f1f0d76dd6 455
XinZhangMS 0:f7f1f0d76dd6 456 static int parse_device_twin_topic_info(const char* resp_topic, bool* patch_msg, size_t* request_id, int* status_code)
XinZhangMS 0:f7f1f0d76dd6 457 {
XinZhangMS 0:f7f1f0d76dd6 458 int result;
XinZhangMS 0:f7f1f0d76dd6 459 STRING_TOKENIZER_HANDLE token_handle = STRING_TOKENIZER_create_from_char(resp_topic);
XinZhangMS 0:f7f1f0d76dd6 460 if (token_handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 461 {
XinZhangMS 0:f7f1f0d76dd6 462 LogError("Failed creating token from device twin topic.");
XinZhangMS 0:f7f1f0d76dd6 463 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 464 *status_code = 0;
XinZhangMS 0:f7f1f0d76dd6 465 *request_id = 0;
XinZhangMS 0:f7f1f0d76dd6 466 *patch_msg = false;
XinZhangMS 0:f7f1f0d76dd6 467 }
XinZhangMS 0:f7f1f0d76dd6 468 else
XinZhangMS 0:f7f1f0d76dd6 469 {
XinZhangMS 0:f7f1f0d76dd6 470 STRING_HANDLE token_value;
XinZhangMS 0:f7f1f0d76dd6 471 if ((token_value = STRING_new()) == NULL)
XinZhangMS 0:f7f1f0d76dd6 472 {
XinZhangMS 0:f7f1f0d76dd6 473 LogError("Failed allocating new string .");
XinZhangMS 0:f7f1f0d76dd6 474 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 475 *status_code = 0;
XinZhangMS 0:f7f1f0d76dd6 476 *request_id = 0;
XinZhangMS 0:f7f1f0d76dd6 477 *patch_msg = false;
XinZhangMS 0:f7f1f0d76dd6 478 }
XinZhangMS 0:f7f1f0d76dd6 479 else
XinZhangMS 0:f7f1f0d76dd6 480 {
XinZhangMS 0:f7f1f0d76dd6 481 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 482 size_t token_count = 0;
XinZhangMS 0:f7f1f0d76dd6 483 while (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/") == 0)
XinZhangMS 0:f7f1f0d76dd6 484 {
XinZhangMS 0:f7f1f0d76dd6 485 if (token_count == 2)
XinZhangMS 0:f7f1f0d76dd6 486 {
XinZhangMS 0:f7f1f0d76dd6 487 if (strcmp(STRING_c_str(token_value), "PATCH") == 0)
XinZhangMS 0:f7f1f0d76dd6 488 {
XinZhangMS 0:f7f1f0d76dd6 489 *patch_msg = true;
XinZhangMS 0:f7f1f0d76dd6 490 *status_code = 0;
XinZhangMS 0:f7f1f0d76dd6 491 *request_id = 0;
XinZhangMS 0:f7f1f0d76dd6 492 result = 0;
XinZhangMS 0:f7f1f0d76dd6 493 break;
XinZhangMS 0:f7f1f0d76dd6 494 }
XinZhangMS 0:f7f1f0d76dd6 495 else
XinZhangMS 0:f7f1f0d76dd6 496 {
XinZhangMS 0:f7f1f0d76dd6 497 *patch_msg = false;
XinZhangMS 0:f7f1f0d76dd6 498 }
XinZhangMS 0:f7f1f0d76dd6 499 }
XinZhangMS 0:f7f1f0d76dd6 500 else if (token_count == 3)
XinZhangMS 0:f7f1f0d76dd6 501 {
XinZhangMS 0:f7f1f0d76dd6 502 *status_code = (int)atol(STRING_c_str(token_value));
XinZhangMS 0:f7f1f0d76dd6 503 if (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/?$rid=") == 0)
XinZhangMS 0:f7f1f0d76dd6 504 {
XinZhangMS 0:f7f1f0d76dd6 505 *request_id = (size_t)atol(STRING_c_str(token_value));
XinZhangMS 0:f7f1f0d76dd6 506 }
XinZhangMS 0:f7f1f0d76dd6 507 *patch_msg = false;
XinZhangMS 0:f7f1f0d76dd6 508 result = 0;
XinZhangMS 0:f7f1f0d76dd6 509 break;
XinZhangMS 0:f7f1f0d76dd6 510 }
XinZhangMS 0:f7f1f0d76dd6 511 token_count++;
XinZhangMS 0:f7f1f0d76dd6 512 }
XinZhangMS 0:f7f1f0d76dd6 513 STRING_delete(token_value);
XinZhangMS 0:f7f1f0d76dd6 514 }
XinZhangMS 0:f7f1f0d76dd6 515 STRING_TOKENIZER_destroy(token_handle);
XinZhangMS 0:f7f1f0d76dd6 516 }
XinZhangMS 0:f7f1f0d76dd6 517 return result;
XinZhangMS 0:f7f1f0d76dd6 518 }
XinZhangMS 0:f7f1f0d76dd6 519
XinZhangMS 0:f7f1f0d76dd6 520 #define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
XinZhangMS 0:f7f1f0d76dd6 521 static int InternStrnicmp(const char* s1, const char* s2, size_t n)
XinZhangMS 0:f7f1f0d76dd6 522 {
XinZhangMS 0:f7f1f0d76dd6 523 int result;
XinZhangMS 0:f7f1f0d76dd6 524
XinZhangMS 0:f7f1f0d76dd6 525 if (s1 == NULL) result = -1;
XinZhangMS 0:f7f1f0d76dd6 526 else if (s2 == NULL) result = 1;
XinZhangMS 0:f7f1f0d76dd6 527 else
XinZhangMS 0:f7f1f0d76dd6 528 {
XinZhangMS 0:f7f1f0d76dd6 529 result = 0;
XinZhangMS 0:f7f1f0d76dd6 530
XinZhangMS 0:f7f1f0d76dd6 531 while (n-- && result == 0)
XinZhangMS 0:f7f1f0d76dd6 532 {
XinZhangMS 0:f7f1f0d76dd6 533 if (*s1 == 0) result = -1;
XinZhangMS 0:f7f1f0d76dd6 534 else if (*s2 == 0) result = 1;
XinZhangMS 0:f7f1f0d76dd6 535 else
XinZhangMS 0:f7f1f0d76dd6 536 {
XinZhangMS 0:f7f1f0d76dd6 537
XinZhangMS 0:f7f1f0d76dd6 538 result = TOLOWER(*s1) - TOLOWER(*s2);
XinZhangMS 0:f7f1f0d76dd6 539 ++s1;
XinZhangMS 0:f7f1f0d76dd6 540 ++s2;
XinZhangMS 0:f7f1f0d76dd6 541 }
XinZhangMS 0:f7f1f0d76dd6 542 }
XinZhangMS 0:f7f1f0d76dd6 543 }
XinZhangMS 0:f7f1f0d76dd6 544
XinZhangMS 0:f7f1f0d76dd6 545 return result;
XinZhangMS 0:f7f1f0d76dd6 546 }
XinZhangMS 0:f7f1f0d76dd6 547
XinZhangMS 0:f7f1f0d76dd6 548
XinZhangMS 0:f7f1f0d76dd6 549 static IOTHUB_IDENTITY_TYPE retrieve_topic_type(const char* topic_resp, const char* input_queue)
XinZhangMS 0:f7f1f0d76dd6 550 {
XinZhangMS 0:f7f1f0d76dd6 551 IOTHUB_IDENTITY_TYPE type;
XinZhangMS 0:f7f1f0d76dd6 552 if (InternStrnicmp(topic_resp, TOPIC_DEVICE_TWIN_PREFIX, sizeof(TOPIC_DEVICE_TWIN_PREFIX) - 1) == 0)
XinZhangMS 0:f7f1f0d76dd6 553 {
XinZhangMS 0:f7f1f0d76dd6 554 type = IOTHUB_TYPE_DEVICE_TWIN;
XinZhangMS 0:f7f1f0d76dd6 555 }
XinZhangMS 0:f7f1f0d76dd6 556 else if (InternStrnicmp(topic_resp, TOPIC_DEVICE_METHOD_PREFIX, sizeof(TOPIC_DEVICE_METHOD_PREFIX) - 1) == 0)
XinZhangMS 0:f7f1f0d76dd6 557 {
XinZhangMS 0:f7f1f0d76dd6 558 type = IOTHUB_TYPE_DEVICE_METHODS;
XinZhangMS 0:f7f1f0d76dd6 559 }
XinZhangMS 0:f7f1f0d76dd6 560 // input_queue contains additional "#" from subscribe, which we strip off on comparing incoming.
XinZhangMS 0:f7f1f0d76dd6 561 else if ((input_queue != NULL) && InternStrnicmp(topic_resp, input_queue, strlen(input_queue) - 1) == 0)
XinZhangMS 0:f7f1f0d76dd6 562 {
XinZhangMS 0:f7f1f0d76dd6 563 type = IOTHUB_TYPE_EVENT_QUEUE;
XinZhangMS 0:f7f1f0d76dd6 564 }
XinZhangMS 0:f7f1f0d76dd6 565 else
XinZhangMS 0:f7f1f0d76dd6 566 {
XinZhangMS 0:f7f1f0d76dd6 567 type = IOTHUB_TYPE_TELEMETRY;
XinZhangMS 0:f7f1f0d76dd6 568 }
XinZhangMS 0:f7f1f0d76dd6 569 return type;
XinZhangMS 0:f7f1f0d76dd6 570
XinZhangMS 0:f7f1f0d76dd6 571 }
XinZhangMS 0:f7f1f0d76dd6 572
XinZhangMS 0:f7f1f0d76dd6 573 static void sendMsgComplete(IOTHUB_MESSAGE_LIST* iothubMsgList, PMQTTTRANSPORT_HANDLE_DATA transport_data, IOTHUB_CLIENT_CONFIRMATION_RESULT confirmResult)
XinZhangMS 0:f7f1f0d76dd6 574 {
XinZhangMS 0:f7f1f0d76dd6 575 DLIST_ENTRY messageCompleted;
XinZhangMS 0:f7f1f0d76dd6 576 DList_InitializeListHead(&messageCompleted);
XinZhangMS 0:f7f1f0d76dd6 577 DList_InsertTailList(&messageCompleted, &(iothubMsgList->entry));
XinZhangMS 0:f7f1f0d76dd6 578 IoTHubClientCore_LL_SendComplete(transport_data->llClientHandle, &messageCompleted, confirmResult);
XinZhangMS 0:f7f1f0d76dd6 579 }
XinZhangMS 0:f7f1f0d76dd6 580
XinZhangMS 0:f7f1f0d76dd6 581 static int addUserPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr, bool urlencode)
XinZhangMS 0:f7f1f0d76dd6 582 {
XinZhangMS 0:f7f1f0d76dd6 583 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 584 const char* const* propertyKeys;
XinZhangMS 0:f7f1f0d76dd6 585 const char* const* propertyValues;
XinZhangMS 0:f7f1f0d76dd6 586 size_t propertyCount;
XinZhangMS 0:f7f1f0d76dd6 587 size_t index = *index_ptr;
XinZhangMS 0:f7f1f0d76dd6 588 MAP_HANDLE properties_map = IoTHubMessage_Properties(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 589 if (properties_map != NULL)
XinZhangMS 0:f7f1f0d76dd6 590 {
XinZhangMS 0:f7f1f0d76dd6 591 if (Map_GetInternals(properties_map, &propertyKeys, &propertyValues, &propertyCount) != MAP_OK)
XinZhangMS 0:f7f1f0d76dd6 592 {
XinZhangMS 0:f7f1f0d76dd6 593 LogError("Failed to get the internals of the property map.");
XinZhangMS 0:f7f1f0d76dd6 594 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 595 }
XinZhangMS 0:f7f1f0d76dd6 596 else
XinZhangMS 0:f7f1f0d76dd6 597 {
XinZhangMS 0:f7f1f0d76dd6 598 if (propertyCount != 0)
XinZhangMS 0:f7f1f0d76dd6 599 {
XinZhangMS 0:f7f1f0d76dd6 600 for (index = 0; index < propertyCount && result == 0; index++)
XinZhangMS 0:f7f1f0d76dd6 601 {
XinZhangMS 0:f7f1f0d76dd6 602 if (urlencode)
XinZhangMS 0:f7f1f0d76dd6 603 {
XinZhangMS 0:f7f1f0d76dd6 604 STRING_HANDLE property_key = URL_EncodeString(propertyKeys[index]);
XinZhangMS 0:f7f1f0d76dd6 605 STRING_HANDLE property_value = URL_EncodeString(propertyValues[index]);
XinZhangMS 0:f7f1f0d76dd6 606 if ((property_key == NULL) || (property_value == NULL))
XinZhangMS 0:f7f1f0d76dd6 607 {
XinZhangMS 0:f7f1f0d76dd6 608 LogError("Failed URL Encoding properties");
XinZhangMS 0:f7f1f0d76dd6 609 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 610 }
XinZhangMS 0:f7f1f0d76dd6 611 else if (STRING_sprintf(topic_string, "%s=%s%s", STRING_c_str(property_key), STRING_c_str(property_value), propertyCount - 1 == index ? "" : PROPERTY_SEPARATOR) != 0)
XinZhangMS 0:f7f1f0d76dd6 612 {
XinZhangMS 0:f7f1f0d76dd6 613 LogError("Failed constructing property string.");
XinZhangMS 0:f7f1f0d76dd6 614 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 615 }
XinZhangMS 0:f7f1f0d76dd6 616 STRING_delete(property_key);
XinZhangMS 0:f7f1f0d76dd6 617 STRING_delete(property_value);
XinZhangMS 0:f7f1f0d76dd6 618 }
XinZhangMS 0:f7f1f0d76dd6 619 else
XinZhangMS 0:f7f1f0d76dd6 620 {
XinZhangMS 0:f7f1f0d76dd6 621 if (STRING_sprintf(topic_string, "%s=%s%s", propertyKeys[index], propertyValues[index], propertyCount - 1 == index ? "" : PROPERTY_SEPARATOR) != 0)
XinZhangMS 0:f7f1f0d76dd6 622 {
XinZhangMS 0:f7f1f0d76dd6 623 LogError("Failed constructing property string.");
XinZhangMS 0:f7f1f0d76dd6 624 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 625 }
XinZhangMS 0:f7f1f0d76dd6 626 }
XinZhangMS 0:f7f1f0d76dd6 627 }
XinZhangMS 0:f7f1f0d76dd6 628 }
XinZhangMS 0:f7f1f0d76dd6 629 }
XinZhangMS 0:f7f1f0d76dd6 630 }
XinZhangMS 0:f7f1f0d76dd6 631 *index_ptr = index;
XinZhangMS 0:f7f1f0d76dd6 632 return result;
XinZhangMS 0:f7f1f0d76dd6 633 }
XinZhangMS 0:f7f1f0d76dd6 634
XinZhangMS 0:f7f1f0d76dd6 635 static int addSystemPropertyToTopicString(STRING_HANDLE topic_string, size_t index, const char* property_key, const char* property_value, bool urlencode)
XinZhangMS 0:f7f1f0d76dd6 636 {
XinZhangMS 0:f7f1f0d76dd6 637 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 638
XinZhangMS 0:f7f1f0d76dd6 639 if (urlencode)
XinZhangMS 0:f7f1f0d76dd6 640 {
XinZhangMS 0:f7f1f0d76dd6 641 STRING_HANDLE encoded_property_value = URL_EncodeString(property_value);
XinZhangMS 0:f7f1f0d76dd6 642 if (encoded_property_value == NULL)
XinZhangMS 0:f7f1f0d76dd6 643 {
XinZhangMS 0:f7f1f0d76dd6 644 LogError("Failed URL encoding %s.", property_key);
XinZhangMS 0:f7f1f0d76dd6 645 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 646 }
XinZhangMS 0:f7f1f0d76dd6 647 else if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, property_key, STRING_c_str(encoded_property_value)) != 0)
XinZhangMS 0:f7f1f0d76dd6 648 {
XinZhangMS 0:f7f1f0d76dd6 649 LogError("Failed setting %s.", property_key);
XinZhangMS 0:f7f1f0d76dd6 650 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 651 }
XinZhangMS 0:f7f1f0d76dd6 652 STRING_delete(encoded_property_value);
XinZhangMS 0:f7f1f0d76dd6 653 }
XinZhangMS 0:f7f1f0d76dd6 654 else
XinZhangMS 0:f7f1f0d76dd6 655 {
XinZhangMS 0:f7f1f0d76dd6 656 if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, property_key, property_value) != 0)
XinZhangMS 0:f7f1f0d76dd6 657 {
XinZhangMS 0:f7f1f0d76dd6 658 LogError("Failed setting %s.", property_key);
XinZhangMS 0:f7f1f0d76dd6 659 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 660 }
XinZhangMS 0:f7f1f0d76dd6 661 }
XinZhangMS 0:f7f1f0d76dd6 662 return result;
XinZhangMS 0:f7f1f0d76dd6 663 }
XinZhangMS 0:f7f1f0d76dd6 664
XinZhangMS 0:f7f1f0d76dd6 665 static int addSystemPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr, bool urlencode)
XinZhangMS 0:f7f1f0d76dd6 666 {
XinZhangMS 0:f7f1f0d76dd6 667 (void)urlencode;
XinZhangMS 0:f7f1f0d76dd6 668 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 669 size_t index = *index_ptr;
XinZhangMS 0:f7f1f0d76dd6 670
XinZhangMS 0:f7f1f0d76dd6 671 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_052: [ IoTHubTransport_MQTT_Common_DoWork shall check for the CorrelationId property and if found add the value as a system property in the format of $.cid=<id> ] */
XinZhangMS 0:f7f1f0d76dd6 672 const char* correlation_id = IoTHubMessage_GetCorrelationId(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 673 if (correlation_id != NULL)
XinZhangMS 0:f7f1f0d76dd6 674 {
XinZhangMS 0:f7f1f0d76dd6 675 result = addSystemPropertyToTopicString(topic_string, index, CORRELATION_ID_PROPERTY, correlation_id, urlencode);
XinZhangMS 0:f7f1f0d76dd6 676 index++;
XinZhangMS 0:f7f1f0d76dd6 677 }
XinZhangMS 0:f7f1f0d76dd6 678 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_053: [ IoTHubTransport_MQTT_Common_DoWork shall check for the MessageId property and if found add the value as a system property in the format of $.mid=<id> ] */
XinZhangMS 0:f7f1f0d76dd6 679 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 680 {
XinZhangMS 0:f7f1f0d76dd6 681 const char* msg_id = IoTHubMessage_GetMessageId(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 682 if (msg_id != NULL)
XinZhangMS 0:f7f1f0d76dd6 683 {
XinZhangMS 0:f7f1f0d76dd6 684 result = addSystemPropertyToTopicString(topic_string, index, MESSAGE_ID_PROPERTY, msg_id, urlencode);
XinZhangMS 0:f7f1f0d76dd6 685 index++;
XinZhangMS 0:f7f1f0d76dd6 686 }
XinZhangMS 0:f7f1f0d76dd6 687 }
XinZhangMS 0:f7f1f0d76dd6 688 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_010: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the ContentType property and if found add the `value` as a system property in the format of `$.ct=<value>` ]
XinZhangMS 0:f7f1f0d76dd6 689 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 690 {
XinZhangMS 0:f7f1f0d76dd6 691 const char* content_type = IoTHubMessage_GetContentTypeSystemProperty(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 692 if (content_type != NULL)
XinZhangMS 0:f7f1f0d76dd6 693 {
XinZhangMS 0:f7f1f0d76dd6 694 result = addSystemPropertyToTopicString(topic_string, index, CONTENT_TYPE_PROPERTY, content_type, urlencode);
XinZhangMS 0:f7f1f0d76dd6 695 index++;
XinZhangMS 0:f7f1f0d76dd6 696 }
XinZhangMS 0:f7f1f0d76dd6 697 }
XinZhangMS 0:f7f1f0d76dd6 698 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_011: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the ContentEncoding property and if found add the `value` as a system property in the format of `$.ce=<value>` ]
XinZhangMS 0:f7f1f0d76dd6 699 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 700 {
XinZhangMS 0:f7f1f0d76dd6 701 const char* content_encoding = IoTHubMessage_GetContentEncodingSystemProperty(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 702 if (content_encoding != NULL)
XinZhangMS 0:f7f1f0d76dd6 703 {
XinZhangMS 0:f7f1f0d76dd6 704 result = addSystemPropertyToTopicString(topic_string, index, CONTENT_ENCODING_PROPERTY, content_encoding, urlencode);
XinZhangMS 0:f7f1f0d76dd6 705 index++;
XinZhangMS 0:f7f1f0d76dd6 706 }
XinZhangMS 0:f7f1f0d76dd6 707 }
XinZhangMS 0:f7f1f0d76dd6 708 *index_ptr = index;
XinZhangMS 0:f7f1f0d76dd6 709 return result;
XinZhangMS 0:f7f1f0d76dd6 710 }
XinZhangMS 0:f7f1f0d76dd6 711
XinZhangMS 0:f7f1f0d76dd6 712 static int addDiagnosticPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, STRING_HANDLE topic_string, size_t* index_ptr)
XinZhangMS 0:f7f1f0d76dd6 713 {
XinZhangMS 0:f7f1f0d76dd6 714 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 715 size_t index = *index_ptr;
XinZhangMS 0:f7f1f0d76dd6 716
XinZhangMS 0:f7f1f0d76dd6 717 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_014: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the diagnostic properties including diagid and diagCreationTimeUtc and if found both add them as system property in the format of `$.diagid` and `$.diagctx` respectively]
XinZhangMS 0:f7f1f0d76dd6 718 const IOTHUB_MESSAGE_DIAGNOSTIC_PROPERTY_DATA* diagnosticData = IoTHubMessage_GetDiagnosticPropertyData(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 719 if (diagnosticData != NULL)
XinZhangMS 0:f7f1f0d76dd6 720 {
XinZhangMS 0:f7f1f0d76dd6 721 const char* diag_id = diagnosticData->diagnosticId;
XinZhangMS 0:f7f1f0d76dd6 722 const char* creation_time_utc = diagnosticData->diagnosticCreationTimeUtc;
XinZhangMS 0:f7f1f0d76dd6 723 //diagid and creationtimeutc must be present/unpresent simultaneously
XinZhangMS 0:f7f1f0d76dd6 724 if (diag_id != NULL && creation_time_utc != NULL)
XinZhangMS 0:f7f1f0d76dd6 725 {
XinZhangMS 0:f7f1f0d76dd6 726 if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, DIAGNOSTIC_ID_PROPERTY, diag_id) != 0)
XinZhangMS 0:f7f1f0d76dd6 727 {
XinZhangMS 0:f7f1f0d76dd6 728 LogError("Failed setting diagnostic id");
XinZhangMS 0:f7f1f0d76dd6 729 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 730 }
XinZhangMS 0:f7f1f0d76dd6 731 index++;
XinZhangMS 0:f7f1f0d76dd6 732
XinZhangMS 0:f7f1f0d76dd6 733 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 734 {
XinZhangMS 0:f7f1f0d76dd6 735 //construct diagnostic context, it should be urlencode(key1=value1,key2=value2)
XinZhangMS 0:f7f1f0d76dd6 736 STRING_HANDLE diagContextHandle = STRING_construct_sprintf("%s=%s", DIAGNOSTIC_CONTEXT_CREATION_TIME_UTC_PROPERTY, creation_time_utc);
XinZhangMS 0:f7f1f0d76dd6 737 if (diagContextHandle == NULL)
XinZhangMS 0:f7f1f0d76dd6 738 {
XinZhangMS 0:f7f1f0d76dd6 739 LogError("Failed constructing diagnostic context");
XinZhangMS 0:f7f1f0d76dd6 740 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 741 }
XinZhangMS 0:f7f1f0d76dd6 742 else
XinZhangMS 0:f7f1f0d76dd6 743 {
XinZhangMS 0:f7f1f0d76dd6 744 //Add other diagnostic context properties here if have more
XinZhangMS 0:f7f1f0d76dd6 745 STRING_HANDLE encodedContextValueHandle = URL_Encode(diagContextHandle);
XinZhangMS 0:f7f1f0d76dd6 746 const char* encodedContextValueString = NULL;
XinZhangMS 0:f7f1f0d76dd6 747 if (encodedContextValueHandle != NULL &&
XinZhangMS 0:f7f1f0d76dd6 748 (encodedContextValueString = STRING_c_str(encodedContextValueHandle)) != NULL)
XinZhangMS 0:f7f1f0d76dd6 749 {
XinZhangMS 0:f7f1f0d76dd6 750 if (STRING_sprintf(topic_string, "%s%%24.%s=%s", index == 0 ? "" : PROPERTY_SEPARATOR, DIAGNOSTIC_CONTEXT_PROPERTY, encodedContextValueString) != 0)
XinZhangMS 0:f7f1f0d76dd6 751 {
XinZhangMS 0:f7f1f0d76dd6 752 LogError("Failed setting diagnostic context");
XinZhangMS 0:f7f1f0d76dd6 753 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 754 }
XinZhangMS 0:f7f1f0d76dd6 755 STRING_delete(encodedContextValueHandle);
XinZhangMS 0:f7f1f0d76dd6 756 encodedContextValueHandle = NULL;
XinZhangMS 0:f7f1f0d76dd6 757 }
XinZhangMS 0:f7f1f0d76dd6 758 else
XinZhangMS 0:f7f1f0d76dd6 759 {
XinZhangMS 0:f7f1f0d76dd6 760 LogError("Failed encoding diagnostic context value");
XinZhangMS 0:f7f1f0d76dd6 761 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 762 }
XinZhangMS 0:f7f1f0d76dd6 763 STRING_delete(diagContextHandle);
XinZhangMS 0:f7f1f0d76dd6 764 diagContextHandle = NULL;
XinZhangMS 0:f7f1f0d76dd6 765 index++;
XinZhangMS 0:f7f1f0d76dd6 766 }
XinZhangMS 0:f7f1f0d76dd6 767 }
XinZhangMS 0:f7f1f0d76dd6 768 }
XinZhangMS 0:f7f1f0d76dd6 769 else if (diag_id != NULL || creation_time_utc != NULL)
XinZhangMS 0:f7f1f0d76dd6 770 {
XinZhangMS 0:f7f1f0d76dd6 771 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_015: [ `IoTHubTransport_MQTT_Common_DoWork` shall check whether diagid and diagCreationTimeUtc be present simultaneously, treat as error if not]
XinZhangMS 0:f7f1f0d76dd6 772 LogError("diagid and diagcreationtimeutc must be present simultaneously.");
XinZhangMS 0:f7f1f0d76dd6 773 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 774 }
XinZhangMS 0:f7f1f0d76dd6 775 }
XinZhangMS 0:f7f1f0d76dd6 776 return result;
XinZhangMS 0:f7f1f0d76dd6 777 }
XinZhangMS 0:f7f1f0d76dd6 778
XinZhangMS 0:f7f1f0d76dd6 779
XinZhangMS 0:f7f1f0d76dd6 780 static STRING_HANDLE addPropertiesTouMqttMessage(IOTHUB_MESSAGE_HANDLE iothub_message_handle, const char* eventTopic, bool urlencode)
XinZhangMS 0:f7f1f0d76dd6 781 {
XinZhangMS 0:f7f1f0d76dd6 782 size_t index = 0;
XinZhangMS 0:f7f1f0d76dd6 783 STRING_HANDLE result = STRING_construct(eventTopic);
XinZhangMS 0:f7f1f0d76dd6 784 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 785 {
XinZhangMS 0:f7f1f0d76dd6 786 LogError("Failed to create event topic string handle");
XinZhangMS 0:f7f1f0d76dd6 787 }
XinZhangMS 0:f7f1f0d76dd6 788 else if (addUserPropertiesTouMqttMessage(iothub_message_handle, result, &index, urlencode) != 0)
XinZhangMS 0:f7f1f0d76dd6 789 {
XinZhangMS 0:f7f1f0d76dd6 790 LogError("Failed adding Properties to uMQTT Message");
XinZhangMS 0:f7f1f0d76dd6 791 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 792 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 793 }
XinZhangMS 0:f7f1f0d76dd6 794 else if (addSystemPropertiesTouMqttMessage(iothub_message_handle, result, &index, urlencode) != 0)
XinZhangMS 0:f7f1f0d76dd6 795 {
XinZhangMS 0:f7f1f0d76dd6 796 LogError("Failed adding System Properties to uMQTT Message");
XinZhangMS 0:f7f1f0d76dd6 797 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 798 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 799 }
XinZhangMS 0:f7f1f0d76dd6 800 else if (addDiagnosticPropertiesTouMqttMessage(iothub_message_handle, result, &index) != 0)
XinZhangMS 0:f7f1f0d76dd6 801 {
XinZhangMS 0:f7f1f0d76dd6 802 LogError("Failed adding Diagnostic Properties to uMQTT Message");
XinZhangMS 0:f7f1f0d76dd6 803 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 804 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 805 }
XinZhangMS 0:f7f1f0d76dd6 806
XinZhangMS 0:f7f1f0d76dd6 807 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_060: [ `IoTHubTransport_MQTT_Common_DoWork` shall check for the OutputName property and if found add the alue as a system property in the format of $.on=<value> ]
XinZhangMS 0:f7f1f0d76dd6 808 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 809 {
XinZhangMS 0:f7f1f0d76dd6 810 const char* output_name = IoTHubMessage_GetOutputName(iothub_message_handle);
XinZhangMS 0:f7f1f0d76dd6 811 if (output_name != NULL)
XinZhangMS 0:f7f1f0d76dd6 812 {
XinZhangMS 0:f7f1f0d76dd6 813 if (STRING_sprintf(result, "%s%%24.on=%s/", index == 0 ? "" : PROPERTY_SEPARATOR, output_name) != 0)
XinZhangMS 0:f7f1f0d76dd6 814 {
XinZhangMS 0:f7f1f0d76dd6 815 LogError("Failed setting output name.");
XinZhangMS 0:f7f1f0d76dd6 816 STRING_delete(result);
XinZhangMS 0:f7f1f0d76dd6 817 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 818 }
XinZhangMS 0:f7f1f0d76dd6 819 index++;
XinZhangMS 0:f7f1f0d76dd6 820 }
XinZhangMS 0:f7f1f0d76dd6 821 }
XinZhangMS 0:f7f1f0d76dd6 822
XinZhangMS 0:f7f1f0d76dd6 823 return result;
XinZhangMS 0:f7f1f0d76dd6 824 }
XinZhangMS 0:f7f1f0d76dd6 825
XinZhangMS 0:f7f1f0d76dd6 826 static int publish_mqtt_telemetry_msg(PMQTTTRANSPORT_HANDLE_DATA transport_data, MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry, const unsigned char* payload, size_t len)
XinZhangMS 0:f7f1f0d76dd6 827 {
XinZhangMS 0:f7f1f0d76dd6 828 int result;
XinZhangMS 0:f7f1f0d76dd6 829 STRING_HANDLE msgTopic = addPropertiesTouMqttMessage(mqttMsgEntry->iotHubMessageEntry->messageHandle, STRING_c_str(transport_data->topic_MqttEvent), transport_data->auto_url_encode_decode);
XinZhangMS 0:f7f1f0d76dd6 830 if (msgTopic == NULL)
XinZhangMS 0:f7f1f0d76dd6 831 {
XinZhangMS 0:f7f1f0d76dd6 832 LogError("Failed adding properties to mqtt message");
XinZhangMS 0:f7f1f0d76dd6 833 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 834 }
XinZhangMS 0:f7f1f0d76dd6 835 else
XinZhangMS 0:f7f1f0d76dd6 836 {
XinZhangMS 0:f7f1f0d76dd6 837 MQTT_MESSAGE_HANDLE mqttMsg = mqttmessage_create(mqttMsgEntry->packet_id, STRING_c_str(msgTopic), DELIVER_AT_LEAST_ONCE, payload, len);
XinZhangMS 0:f7f1f0d76dd6 838 if (mqttMsg == NULL)
XinZhangMS 0:f7f1f0d76dd6 839 {
XinZhangMS 0:f7f1f0d76dd6 840 LogError("Failed creating mqtt message");
XinZhangMS 0:f7f1f0d76dd6 841 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 842 }
XinZhangMS 0:f7f1f0d76dd6 843 else
XinZhangMS 0:f7f1f0d76dd6 844 {
XinZhangMS 0:f7f1f0d76dd6 845 if (tickcounter_get_current_ms(transport_data->msgTickCounter, &mqttMsgEntry->msgPublishTime) != 0)
XinZhangMS 0:f7f1f0d76dd6 846 {
XinZhangMS 0:f7f1f0d76dd6 847 LogError("Failed retrieving tickcounter info");
XinZhangMS 0:f7f1f0d76dd6 848 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 849 }
XinZhangMS 0:f7f1f0d76dd6 850 else
XinZhangMS 0:f7f1f0d76dd6 851 {
XinZhangMS 0:f7f1f0d76dd6 852 if (mqtt_client_publish(transport_data->mqttClient, mqttMsg) != 0)
XinZhangMS 0:f7f1f0d76dd6 853 {
XinZhangMS 0:f7f1f0d76dd6 854 LogError("Failed attempting to publish mqtt message");
XinZhangMS 0:f7f1f0d76dd6 855 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 856 }
XinZhangMS 0:f7f1f0d76dd6 857 else
XinZhangMS 0:f7f1f0d76dd6 858 {
XinZhangMS 0:f7f1f0d76dd6 859 mqttMsgEntry->retryCount++;
XinZhangMS 0:f7f1f0d76dd6 860 result = 0;
XinZhangMS 0:f7f1f0d76dd6 861 }
XinZhangMS 0:f7f1f0d76dd6 862 }
XinZhangMS 0:f7f1f0d76dd6 863 mqttmessage_destroy(mqttMsg);
XinZhangMS 0:f7f1f0d76dd6 864 }
XinZhangMS 0:f7f1f0d76dd6 865 STRING_delete(msgTopic);
XinZhangMS 0:f7f1f0d76dd6 866 }
XinZhangMS 0:f7f1f0d76dd6 867 return result;
XinZhangMS 0:f7f1f0d76dd6 868 }
XinZhangMS 0:f7f1f0d76dd6 869
XinZhangMS 0:f7f1f0d76dd6 870 static int publish_device_method_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, int status_code, STRING_HANDLE request_id, const unsigned char* response, size_t response_size)
XinZhangMS 0:f7f1f0d76dd6 871 {
XinZhangMS 0:f7f1f0d76dd6 872 int result;
XinZhangMS 0:f7f1f0d76dd6 873 uint16_t packet_id = get_next_packet_id(transport_data);
XinZhangMS 0:f7f1f0d76dd6 874
XinZhangMS 0:f7f1f0d76dd6 875 STRING_HANDLE msg_topic = STRING_construct_sprintf(DEVICE_METHOD_RESPONSE_TOPIC, status_code, STRING_c_str(request_id));
XinZhangMS 0:f7f1f0d76dd6 876 if (msg_topic == NULL)
XinZhangMS 0:f7f1f0d76dd6 877 {
XinZhangMS 0:f7f1f0d76dd6 878 LogError("Failed constructing message topic.");
XinZhangMS 0:f7f1f0d76dd6 879 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 880 }
XinZhangMS 0:f7f1f0d76dd6 881 else
XinZhangMS 0:f7f1f0d76dd6 882 {
XinZhangMS 0:f7f1f0d76dd6 883 MQTT_MESSAGE_HANDLE mqtt_get_msg = mqttmessage_create(packet_id, STRING_c_str(msg_topic), DELIVER_AT_MOST_ONCE, response, response_size);
XinZhangMS 0:f7f1f0d76dd6 884 if (mqtt_get_msg == NULL)
XinZhangMS 0:f7f1f0d76dd6 885 {
XinZhangMS 0:f7f1f0d76dd6 886 LogError("Failed constructing mqtt message.");
XinZhangMS 0:f7f1f0d76dd6 887 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 888 }
XinZhangMS 0:f7f1f0d76dd6 889 else
XinZhangMS 0:f7f1f0d76dd6 890 {
XinZhangMS 0:f7f1f0d76dd6 891 if (mqtt_client_publish(transport_data->mqttClient, mqtt_get_msg) != 0)
XinZhangMS 0:f7f1f0d76dd6 892 {
XinZhangMS 0:f7f1f0d76dd6 893 LogError("Failed publishing to mqtt client.");
XinZhangMS 0:f7f1f0d76dd6 894 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 895 }
XinZhangMS 0:f7f1f0d76dd6 896 else
XinZhangMS 0:f7f1f0d76dd6 897 {
XinZhangMS 0:f7f1f0d76dd6 898 result = 0;
XinZhangMS 0:f7f1f0d76dd6 899 }
XinZhangMS 0:f7f1f0d76dd6 900 mqttmessage_destroy(mqtt_get_msg);
XinZhangMS 0:f7f1f0d76dd6 901 }
XinZhangMS 0:f7f1f0d76dd6 902 STRING_delete(msg_topic);
XinZhangMS 0:f7f1f0d76dd6 903 }
XinZhangMS 0:f7f1f0d76dd6 904 return result;
XinZhangMS 0:f7f1f0d76dd6 905 }
XinZhangMS 0:f7f1f0d76dd6 906
XinZhangMS 0:f7f1f0d76dd6 907 static int publish_device_twin_get_message(MQTTTRANSPORT_HANDLE_DATA* transport_data)
XinZhangMS 0:f7f1f0d76dd6 908 {
XinZhangMS 0:f7f1f0d76dd6 909 int result;
XinZhangMS 0:f7f1f0d76dd6 910 MQTT_DEVICE_TWIN_ITEM* mqtt_info = (MQTT_DEVICE_TWIN_ITEM*)malloc(sizeof(MQTT_DEVICE_TWIN_ITEM));
XinZhangMS 0:f7f1f0d76dd6 911 if (mqtt_info == NULL)
XinZhangMS 0:f7f1f0d76dd6 912 {
XinZhangMS 0:f7f1f0d76dd6 913 LogError("Failed allocating device twin data.");
XinZhangMS 0:f7f1f0d76dd6 914 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 915 }
XinZhangMS 0:f7f1f0d76dd6 916 else
XinZhangMS 0:f7f1f0d76dd6 917 {
XinZhangMS 0:f7f1f0d76dd6 918 mqtt_info->packet_id = get_next_packet_id(transport_data);
XinZhangMS 0:f7f1f0d76dd6 919 mqtt_info->iothub_msg_id = 0;
XinZhangMS 0:f7f1f0d76dd6 920 mqtt_info->device_twin_msg_type = RETRIEVE_PROPERTIES;
XinZhangMS 0:f7f1f0d76dd6 921 mqtt_info->retryCount = 0;
XinZhangMS 0:f7f1f0d76dd6 922 mqtt_info->msgPublishTime = 0;
XinZhangMS 0:f7f1f0d76dd6 923 mqtt_info->iothub_type = IOTHUB_TYPE_DEVICE_TWIN;
XinZhangMS 0:f7f1f0d76dd6 924 mqtt_info->device_twin_data = NULL;
XinZhangMS 0:f7f1f0d76dd6 925 STRING_HANDLE msg_topic = STRING_construct_sprintf(GET_PROPERTIES_TOPIC, mqtt_info->packet_id);
XinZhangMS 0:f7f1f0d76dd6 926 if (msg_topic == NULL)
XinZhangMS 0:f7f1f0d76dd6 927 {
XinZhangMS 0:f7f1f0d76dd6 928 LogError("Failed constructing get Prop topic.");
XinZhangMS 0:f7f1f0d76dd6 929 free(mqtt_info);
XinZhangMS 0:f7f1f0d76dd6 930 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 931 }
XinZhangMS 0:f7f1f0d76dd6 932 else
XinZhangMS 0:f7f1f0d76dd6 933 {
XinZhangMS 0:f7f1f0d76dd6 934 MQTT_MESSAGE_HANDLE mqtt_get_msg = mqttmessage_create(mqtt_info->packet_id, STRING_c_str(msg_topic), DELIVER_AT_MOST_ONCE, NULL, 0);
XinZhangMS 0:f7f1f0d76dd6 935 if (mqtt_get_msg == NULL)
XinZhangMS 0:f7f1f0d76dd6 936 {
XinZhangMS 0:f7f1f0d76dd6 937 LogError("Failed constructing mqtt message.");
XinZhangMS 0:f7f1f0d76dd6 938 free(mqtt_info);
XinZhangMS 0:f7f1f0d76dd6 939 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 940 }
XinZhangMS 0:f7f1f0d76dd6 941 else
XinZhangMS 0:f7f1f0d76dd6 942 {
XinZhangMS 0:f7f1f0d76dd6 943 if (mqtt_client_publish(transport_data->mqttClient, mqtt_get_msg) != 0)
XinZhangMS 0:f7f1f0d76dd6 944 {
XinZhangMS 0:f7f1f0d76dd6 945 LogError("Failed publishing to mqtt client.");
XinZhangMS 0:f7f1f0d76dd6 946 free(mqtt_info);
XinZhangMS 0:f7f1f0d76dd6 947 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 948 }
XinZhangMS 0:f7f1f0d76dd6 949 else
XinZhangMS 0:f7f1f0d76dd6 950 {
XinZhangMS 0:f7f1f0d76dd6 951 DList_InsertTailList(&transport_data->ack_waiting_queue, &mqtt_info->entry);
XinZhangMS 0:f7f1f0d76dd6 952 result = 0;
XinZhangMS 0:f7f1f0d76dd6 953 }
XinZhangMS 0:f7f1f0d76dd6 954 mqttmessage_destroy(mqtt_get_msg);
XinZhangMS 0:f7f1f0d76dd6 955 }
XinZhangMS 0:f7f1f0d76dd6 956 STRING_delete(msg_topic);
XinZhangMS 0:f7f1f0d76dd6 957 }
XinZhangMS 0:f7f1f0d76dd6 958 }
XinZhangMS 0:f7f1f0d76dd6 959 return result;
XinZhangMS 0:f7f1f0d76dd6 960 }
XinZhangMS 0:f7f1f0d76dd6 961
XinZhangMS 0:f7f1f0d76dd6 962 static int publish_device_twin_message(MQTTTRANSPORT_HANDLE_DATA* transport_data, IOTHUB_DEVICE_TWIN* device_twin_info, MQTT_DEVICE_TWIN_ITEM* mqtt_info)
XinZhangMS 0:f7f1f0d76dd6 963 {
XinZhangMS 0:f7f1f0d76dd6 964 int result;
XinZhangMS 0:f7f1f0d76dd6 965 mqtt_info->packet_id = get_next_packet_id(transport_data);
XinZhangMS 0:f7f1f0d76dd6 966 mqtt_info->device_twin_msg_type = REPORTED_STATE;
XinZhangMS 0:f7f1f0d76dd6 967 STRING_HANDLE msgTopic = STRING_construct_sprintf(REPORTED_PROPERTIES_TOPIC, mqtt_info->packet_id);
XinZhangMS 0:f7f1f0d76dd6 968 if (msgTopic == NULL)
XinZhangMS 0:f7f1f0d76dd6 969 {
XinZhangMS 0:f7f1f0d76dd6 970 LogError("Failed constructing reported prop topic.");
XinZhangMS 0:f7f1f0d76dd6 971 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 972 }
XinZhangMS 0:f7f1f0d76dd6 973 else
XinZhangMS 0:f7f1f0d76dd6 974 {
XinZhangMS 0:f7f1f0d76dd6 975 const CONSTBUFFER* data_buff = CONSTBUFFER_GetContent(device_twin_info->report_data_handle);
XinZhangMS 0:f7f1f0d76dd6 976 MQTT_MESSAGE_HANDLE mqtt_rpt_msg = mqttmessage_create(mqtt_info->packet_id, STRING_c_str(msgTopic), DELIVER_AT_MOST_ONCE, data_buff->buffer, data_buff->size);
XinZhangMS 0:f7f1f0d76dd6 977 if (mqtt_rpt_msg == NULL)
XinZhangMS 0:f7f1f0d76dd6 978 {
XinZhangMS 0:f7f1f0d76dd6 979 LogError("Failed creating mqtt message");
XinZhangMS 0:f7f1f0d76dd6 980 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 981 }
XinZhangMS 0:f7f1f0d76dd6 982 else
XinZhangMS 0:f7f1f0d76dd6 983 {
XinZhangMS 0:f7f1f0d76dd6 984 if (tickcounter_get_current_ms(transport_data->msgTickCounter, &mqtt_info->msgPublishTime) != 0)
XinZhangMS 0:f7f1f0d76dd6 985 {
XinZhangMS 0:f7f1f0d76dd6 986 LogError("Failed retrieving tickcounter info");
XinZhangMS 0:f7f1f0d76dd6 987 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 988 }
XinZhangMS 0:f7f1f0d76dd6 989 else
XinZhangMS 0:f7f1f0d76dd6 990 {
XinZhangMS 0:f7f1f0d76dd6 991 if (mqtt_client_publish(transport_data->mqttClient, mqtt_rpt_msg) != 0)
XinZhangMS 0:f7f1f0d76dd6 992 {
XinZhangMS 0:f7f1f0d76dd6 993 LogError("Failed publishing mqtt message");
XinZhangMS 0:f7f1f0d76dd6 994 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 995 }
XinZhangMS 0:f7f1f0d76dd6 996 else
XinZhangMS 0:f7f1f0d76dd6 997 {
XinZhangMS 0:f7f1f0d76dd6 998 mqtt_info->retryCount++;
XinZhangMS 0:f7f1f0d76dd6 999 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1000 }
XinZhangMS 0:f7f1f0d76dd6 1001 }
XinZhangMS 0:f7f1f0d76dd6 1002 mqttmessage_destroy(mqtt_rpt_msg);
XinZhangMS 0:f7f1f0d76dd6 1003 }
XinZhangMS 0:f7f1f0d76dd6 1004 STRING_delete(msgTopic);
XinZhangMS 0:f7f1f0d76dd6 1005 }
XinZhangMS 0:f7f1f0d76dd6 1006 return result;
XinZhangMS 0:f7f1f0d76dd6 1007 }
XinZhangMS 0:f7f1f0d76dd6 1008
XinZhangMS 0:f7f1f0d76dd6 1009 static void changeStateToSubscribeIfAllowed(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1010 {
XinZhangMS 0:f7f1f0d76dd6 1011 if (transport_data->currPacketState != CONNACK_TYPE &&
XinZhangMS 0:f7f1f0d76dd6 1012 transport_data->currPacketState != CONNECT_TYPE &&
XinZhangMS 0:f7f1f0d76dd6 1013 transport_data->currPacketState != DISCONNECT_TYPE &&
XinZhangMS 0:f7f1f0d76dd6 1014 transport_data->currPacketState != PACKET_TYPE_ERROR)
XinZhangMS 0:f7f1f0d76dd6 1015 {
XinZhangMS 0:f7f1f0d76dd6 1016 transport_data->currPacketState = SUBSCRIBE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1017 }
XinZhangMS 0:f7f1f0d76dd6 1018 }
XinZhangMS 0:f7f1f0d76dd6 1019
XinZhangMS 0:f7f1f0d76dd6 1020 static int subscribeToNotifyStateIfNeeded(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1021 {
XinZhangMS 0:f7f1f0d76dd6 1022 int result;
XinZhangMS 0:f7f1f0d76dd6 1023
XinZhangMS 0:f7f1f0d76dd6 1024 if (transport_data->topic_NotifyState == NULL)
XinZhangMS 0:f7f1f0d76dd6 1025 {
XinZhangMS 0:f7f1f0d76dd6 1026 transport_data->topic_NotifyState = STRING_construct(TOPIC_NOTIFICATION_STATE);
XinZhangMS 0:f7f1f0d76dd6 1027 if (transport_data->topic_NotifyState == NULL)
XinZhangMS 0:f7f1f0d76dd6 1028 {
XinZhangMS 0:f7f1f0d76dd6 1029 LogError("Failure: unable constructing notify state topic");
XinZhangMS 0:f7f1f0d76dd6 1030 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1031 }
XinZhangMS 0:f7f1f0d76dd6 1032 else
XinZhangMS 0:f7f1f0d76dd6 1033 {
XinZhangMS 0:f7f1f0d76dd6 1034 transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1035 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1036 }
XinZhangMS 0:f7f1f0d76dd6 1037 }
XinZhangMS 0:f7f1f0d76dd6 1038 else
XinZhangMS 0:f7f1f0d76dd6 1039 {
XinZhangMS 0:f7f1f0d76dd6 1040 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1041 }
XinZhangMS 0:f7f1f0d76dd6 1042
XinZhangMS 0:f7f1f0d76dd6 1043 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 1044 {
XinZhangMS 0:f7f1f0d76dd6 1045 changeStateToSubscribeIfAllowed(transport_data);
XinZhangMS 0:f7f1f0d76dd6 1046 }
XinZhangMS 0:f7f1f0d76dd6 1047
XinZhangMS 0:f7f1f0d76dd6 1048 return result;
XinZhangMS 0:f7f1f0d76dd6 1049 }
XinZhangMS 0:f7f1f0d76dd6 1050
XinZhangMS 0:f7f1f0d76dd6 1051
XinZhangMS 0:f7f1f0d76dd6 1052 static bool isSystemProperty(const char* tokenData)
XinZhangMS 0:f7f1f0d76dd6 1053 {
XinZhangMS 0:f7f1f0d76dd6 1054 bool result = false;
XinZhangMS 0:f7f1f0d76dd6 1055 size_t propCount = sizeof(sysPropList) / sizeof(sysPropList[0]);
XinZhangMS 0:f7f1f0d76dd6 1056 size_t index = 0;
XinZhangMS 0:f7f1f0d76dd6 1057 for (index = 0; index < propCount; index++)
XinZhangMS 0:f7f1f0d76dd6 1058 {
XinZhangMS 0:f7f1f0d76dd6 1059 if (memcmp(tokenData, sysPropList[index].propName, sysPropList[index].propLength) == 0)
XinZhangMS 0:f7f1f0d76dd6 1060 {
XinZhangMS 0:f7f1f0d76dd6 1061 result = true;
XinZhangMS 0:f7f1f0d76dd6 1062 break;
XinZhangMS 0:f7f1f0d76dd6 1063 }
XinZhangMS 0:f7f1f0d76dd6 1064 }
XinZhangMS 0:f7f1f0d76dd6 1065 return result;
XinZhangMS 0:f7f1f0d76dd6 1066 }
XinZhangMS 0:f7f1f0d76dd6 1067
XinZhangMS 0:f7f1f0d76dd6 1068 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_061: [ If the message is sent to an input queue, `IoTHubTransport_MQTT_Common_DoWork` shall parse out to the input queue name and store it in the message with IoTHubMessage_SetInputName ]
XinZhangMS 0:f7f1f0d76dd6 1069 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_062: [ If IoTHubTransport_MQTT_Common_DoWork receives a malformatted inputQueue, it shall fail ]
XinZhangMS 0:f7f1f0d76dd6 1070 static int addInputNamePropertyToMessage(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name)
XinZhangMS 0:f7f1f0d76dd6 1071 {
XinZhangMS 0:f7f1f0d76dd6 1072 int result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1073 int number_tokens_read = 0;
XinZhangMS 0:f7f1f0d76dd6 1074
XinZhangMS 0:f7f1f0d76dd6 1075 STRING_TOKENIZER_HANDLE token_handle = STRING_TOKENIZER_create_from_char(topic_name);
XinZhangMS 0:f7f1f0d76dd6 1076 if (token_handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 1077 {
XinZhangMS 0:f7f1f0d76dd6 1078 LogError("STRING_TOKENIZER_create_from_char failed\n");
XinZhangMS 0:f7f1f0d76dd6 1079 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1080 }
XinZhangMS 0:f7f1f0d76dd6 1081 else
XinZhangMS 0:f7f1f0d76dd6 1082 {
XinZhangMS 0:f7f1f0d76dd6 1083 STRING_HANDLE token_value;
XinZhangMS 0:f7f1f0d76dd6 1084 if ((token_value = STRING_new()) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1085 {
XinZhangMS 0:f7f1f0d76dd6 1086 LogError("Failed allocating token_value");
XinZhangMS 0:f7f1f0d76dd6 1087 }
XinZhangMS 0:f7f1f0d76dd6 1088 else
XinZhangMS 0:f7f1f0d76dd6 1089 {
XinZhangMS 0:f7f1f0d76dd6 1090 while (STRING_TOKENIZER_get_next_token(token_handle, token_value, "/") == 0)
XinZhangMS 0:f7f1f0d76dd6 1091 {
XinZhangMS 0:f7f1f0d76dd6 1092 number_tokens_read++;
XinZhangMS 0:f7f1f0d76dd6 1093 if (number_tokens_read == (slashes_to_reach_input_name + 1))
XinZhangMS 0:f7f1f0d76dd6 1094 {
XinZhangMS 0:f7f1f0d76dd6 1095 if ((IOTHUB_MESSAGE_OK != IoTHubMessage_SetInputName(IoTHubMessage, STRING_c_str(token_value))))
XinZhangMS 0:f7f1f0d76dd6 1096 {
XinZhangMS 0:f7f1f0d76dd6 1097 LogError("Failed adding input name to msg");
XinZhangMS 0:f7f1f0d76dd6 1098 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1099 }
XinZhangMS 0:f7f1f0d76dd6 1100 else
XinZhangMS 0:f7f1f0d76dd6 1101 {
XinZhangMS 0:f7f1f0d76dd6 1102 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1103 }
XinZhangMS 0:f7f1f0d76dd6 1104 break;
XinZhangMS 0:f7f1f0d76dd6 1105 }
XinZhangMS 0:f7f1f0d76dd6 1106 }
XinZhangMS 0:f7f1f0d76dd6 1107 }
XinZhangMS 0:f7f1f0d76dd6 1108 STRING_delete(token_value);
XinZhangMS 0:f7f1f0d76dd6 1109
XinZhangMS 0:f7f1f0d76dd6 1110 if (number_tokens_read != (slashes_to_reach_input_name + 1))
XinZhangMS 0:f7f1f0d76dd6 1111 {
XinZhangMS 0:f7f1f0d76dd6 1112 LogError("Not enough '/' to contain input name. Got %d, need at least %d", number_tokens_read, (slashes_to_reach_input_name + 1));
XinZhangMS 0:f7f1f0d76dd6 1113 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1114 }
XinZhangMS 0:f7f1f0d76dd6 1115 STRING_TOKENIZER_destroy(token_handle);
XinZhangMS 0:f7f1f0d76dd6 1116 }
XinZhangMS 0:f7f1f0d76dd6 1117
XinZhangMS 0:f7f1f0d76dd6 1118 return result;
XinZhangMS 0:f7f1f0d76dd6 1119 }
XinZhangMS 0:f7f1f0d76dd6 1120
XinZhangMS 0:f7f1f0d76dd6 1121 static int setMqttMessagePropertyIfPossible(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* propName, const char* propValue, size_t nameLen)
XinZhangMS 0:f7f1f0d76dd6 1122 {
XinZhangMS 0:f7f1f0d76dd6 1123 // Not finding a system property to map to isn't an error.
XinZhangMS 0:f7f1f0d76dd6 1124 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 1125
XinZhangMS 0:f7f1f0d76dd6 1126 if (nameLen > 4)
XinZhangMS 0:f7f1f0d76dd6 1127 {
XinZhangMS 0:f7f1f0d76dd6 1128 if (strcmp((const char*)&propName[nameLen - 4], CONNECTION_DEVICE_ID) == 0)
XinZhangMS 0:f7f1f0d76dd6 1129 {
XinZhangMS 0:f7f1f0d76dd6 1130 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_063: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.cdid` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ConnectionDeviceId property ]
XinZhangMS 0:f7f1f0d76dd6 1131 if (IoTHubMessage_SetConnectionDeviceId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1132 {
XinZhangMS 0:f7f1f0d76dd6 1133 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'messageId' property.");
XinZhangMS 0:f7f1f0d76dd6 1134 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1135 }
XinZhangMS 0:f7f1f0d76dd6 1136 return result;
XinZhangMS 0:f7f1f0d76dd6 1137 }
XinZhangMS 0:f7f1f0d76dd6 1138 if (strcmp((const char*)&propName[nameLen - 4], CONNECTION_MODULE_ID_PROPERTY) == 0)
XinZhangMS 0:f7f1f0d76dd6 1139 {
XinZhangMS 0:f7f1f0d76dd6 1140 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_064: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.cmid` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ConnectionModuleId property ]
XinZhangMS 0:f7f1f0d76dd6 1141 if (IoTHubMessage_SetConnectionModuleId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1142 {
XinZhangMS 0:f7f1f0d76dd6 1143 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlationId' property.");
XinZhangMS 0:f7f1f0d76dd6 1144 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1145 }
XinZhangMS 0:f7f1f0d76dd6 1146 return result;
XinZhangMS 0:f7f1f0d76dd6 1147 }
XinZhangMS 0:f7f1f0d76dd6 1148 }
XinZhangMS 0:f7f1f0d76dd6 1149 if (nameLen > 3)
XinZhangMS 0:f7f1f0d76dd6 1150 {
XinZhangMS 0:f7f1f0d76dd6 1151 if (strcmp((const char*)&propName[nameLen - 3], MESSAGE_ID_PROPERTY) == 0)
XinZhangMS 0:f7f1f0d76dd6 1152 {
XinZhangMS 0:f7f1f0d76dd6 1153 if (IoTHubMessage_SetMessageId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1154 {
XinZhangMS 0:f7f1f0d76dd6 1155 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'messageId' property.");
XinZhangMS 0:f7f1f0d76dd6 1156 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1157 }
XinZhangMS 0:f7f1f0d76dd6 1158 return result;
XinZhangMS 0:f7f1f0d76dd6 1159 }
XinZhangMS 0:f7f1f0d76dd6 1160 else if (strcmp((const char*)&propName[nameLen - 3], CORRELATION_ID_PROPERTY) == 0)
XinZhangMS 0:f7f1f0d76dd6 1161 {
XinZhangMS 0:f7f1f0d76dd6 1162 if (IoTHubMessage_SetCorrelationId(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1163 {
XinZhangMS 0:f7f1f0d76dd6 1164 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlationId' property.");
XinZhangMS 0:f7f1f0d76dd6 1165 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1166 }
XinZhangMS 0:f7f1f0d76dd6 1167 return result;
XinZhangMS 0:f7f1f0d76dd6 1168 }
XinZhangMS 0:f7f1f0d76dd6 1169 }
XinZhangMS 0:f7f1f0d76dd6 1170
XinZhangMS 0:f7f1f0d76dd6 1171 if (nameLen > 2)
XinZhangMS 0:f7f1f0d76dd6 1172 {
XinZhangMS 0:f7f1f0d76dd6 1173 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_012: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.ct` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ContentType property ]
XinZhangMS 0:f7f1f0d76dd6 1174 if (strcmp((const char*)&propName[nameLen - 2], CONTENT_TYPE_PROPERTY) == 0)
XinZhangMS 0:f7f1f0d76dd6 1175 {
XinZhangMS 0:f7f1f0d76dd6 1176 if (IoTHubMessage_SetContentTypeSystemProperty(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1177 {
XinZhangMS 0:f7f1f0d76dd6 1178 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'customContentType' property.");
XinZhangMS 0:f7f1f0d76dd6 1179 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1180 }
XinZhangMS 0:f7f1f0d76dd6 1181 return result;
XinZhangMS 0:f7f1f0d76dd6 1182 }
XinZhangMS 0:f7f1f0d76dd6 1183 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_013: [ If type is IOTHUB_TYPE_TELEMETRY and the system property `$.ce` is defined, its value shall be set on the IOTHUB_MESSAGE_HANDLE's ContentEncoding property ]
XinZhangMS 0:f7f1f0d76dd6 1184 else if (strcmp((const char*)&propName[nameLen - 2], CONTENT_ENCODING_PROPERTY) == 0)
XinZhangMS 0:f7f1f0d76dd6 1185 {
XinZhangMS 0:f7f1f0d76dd6 1186 if (IoTHubMessage_SetContentEncodingSystemProperty(IoTHubMessage, propValue) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1187 {
XinZhangMS 0:f7f1f0d76dd6 1188 LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'contentEncoding' property.");
XinZhangMS 0:f7f1f0d76dd6 1189 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1190 }
XinZhangMS 0:f7f1f0d76dd6 1191 return result;
XinZhangMS 0:f7f1f0d76dd6 1192 }
XinZhangMS 0:f7f1f0d76dd6 1193 }
XinZhangMS 0:f7f1f0d76dd6 1194
XinZhangMS 0:f7f1f0d76dd6 1195 return result;
XinZhangMS 0:f7f1f0d76dd6 1196 }
XinZhangMS 0:f7f1f0d76dd6 1197
XinZhangMS 0:f7f1f0d76dd6 1198 static int extractMqttProperties(IOTHUB_MESSAGE_HANDLE IoTHubMessage, const char* topic_name, bool urldecode)
XinZhangMS 0:f7f1f0d76dd6 1199 {
XinZhangMS 0:f7f1f0d76dd6 1200 int result;
XinZhangMS 0:f7f1f0d76dd6 1201 STRING_HANDLE mqttTopic = STRING_construct(topic_name);
XinZhangMS 0:f7f1f0d76dd6 1202 if (mqttTopic == NULL)
XinZhangMS 0:f7f1f0d76dd6 1203 {
XinZhangMS 0:f7f1f0d76dd6 1204 LogError("Failure constructing string topic name.");
XinZhangMS 0:f7f1f0d76dd6 1205 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1206 }
XinZhangMS 0:f7f1f0d76dd6 1207 else
XinZhangMS 0:f7f1f0d76dd6 1208 {
XinZhangMS 0:f7f1f0d76dd6 1209 STRING_TOKENIZER_HANDLE token = STRING_TOKENIZER_create(mqttTopic);
XinZhangMS 0:f7f1f0d76dd6 1210 if (token != NULL)
XinZhangMS 0:f7f1f0d76dd6 1211 {
XinZhangMS 0:f7f1f0d76dd6 1212 MAP_HANDLE propertyMap = IoTHubMessage_Properties(IoTHubMessage);
XinZhangMS 0:f7f1f0d76dd6 1213 if (propertyMap == NULL)
XinZhangMS 0:f7f1f0d76dd6 1214 {
XinZhangMS 0:f7f1f0d76dd6 1215 LogError("Failure to retrieve IoTHubMessage_properties.");
XinZhangMS 0:f7f1f0d76dd6 1216 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1217 }
XinZhangMS 0:f7f1f0d76dd6 1218 else
XinZhangMS 0:f7f1f0d76dd6 1219 {
XinZhangMS 0:f7f1f0d76dd6 1220 STRING_HANDLE output = STRING_new();
XinZhangMS 0:f7f1f0d76dd6 1221 if (output == NULL)
XinZhangMS 0:f7f1f0d76dd6 1222 {
XinZhangMS 0:f7f1f0d76dd6 1223 LogError("Failure to allocate STRING_new.");
XinZhangMS 0:f7f1f0d76dd6 1224 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1225 }
XinZhangMS 0:f7f1f0d76dd6 1226 else
XinZhangMS 0:f7f1f0d76dd6 1227 {
XinZhangMS 0:f7f1f0d76dd6 1228 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1229
XinZhangMS 0:f7f1f0d76dd6 1230 while (STRING_TOKENIZER_get_next_token(token, output, PROPERTY_SEPARATOR) == 0 && result == 0)
XinZhangMS 0:f7f1f0d76dd6 1231 {
XinZhangMS 0:f7f1f0d76dd6 1232 const char* tokenData = STRING_c_str(output);
XinZhangMS 0:f7f1f0d76dd6 1233 size_t tokenLen = strlen(tokenData);
XinZhangMS 0:f7f1f0d76dd6 1234 if (tokenData == NULL || tokenLen == 0)
XinZhangMS 0:f7f1f0d76dd6 1235 {
XinZhangMS 0:f7f1f0d76dd6 1236 break;
XinZhangMS 0:f7f1f0d76dd6 1237 }
XinZhangMS 0:f7f1f0d76dd6 1238 else
XinZhangMS 0:f7f1f0d76dd6 1239 {
XinZhangMS 0:f7f1f0d76dd6 1240 if (isSystemProperty(tokenData))
XinZhangMS 0:f7f1f0d76dd6 1241 {
XinZhangMS 0:f7f1f0d76dd6 1242 const char* iterator = tokenData;
XinZhangMS 0:f7f1f0d76dd6 1243 while (iterator != NULL && *iterator != '\0' && result == 0)
XinZhangMS 0:f7f1f0d76dd6 1244 {
XinZhangMS 0:f7f1f0d76dd6 1245 if (*iterator == '=')
XinZhangMS 0:f7f1f0d76dd6 1246 {
XinZhangMS 0:f7f1f0d76dd6 1247 size_t nameLen = iterator - tokenData;
XinZhangMS 0:f7f1f0d76dd6 1248 char* propName = malloc(nameLen + 1);
XinZhangMS 0:f7f1f0d76dd6 1249
XinZhangMS 0:f7f1f0d76dd6 1250 size_t valLen = tokenLen - (nameLen + 1) + 1;
XinZhangMS 0:f7f1f0d76dd6 1251 char* propValue = malloc(valLen + 1);
XinZhangMS 0:f7f1f0d76dd6 1252
XinZhangMS 0:f7f1f0d76dd6 1253 if (propName == NULL || propValue == NULL)
XinZhangMS 0:f7f1f0d76dd6 1254 {
XinZhangMS 0:f7f1f0d76dd6 1255 LogError("Failed allocating property name (%p) and/or value (%p)", propName, propValue);
XinZhangMS 0:f7f1f0d76dd6 1256 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1257 }
XinZhangMS 0:f7f1f0d76dd6 1258 else
XinZhangMS 0:f7f1f0d76dd6 1259 {
XinZhangMS 0:f7f1f0d76dd6 1260 strncpy(propName, tokenData, nameLen);
XinZhangMS 0:f7f1f0d76dd6 1261 propName[nameLen] = '\0';
XinZhangMS 0:f7f1f0d76dd6 1262
XinZhangMS 0:f7f1f0d76dd6 1263 strncpy(propValue, iterator + 1, valLen);
XinZhangMS 0:f7f1f0d76dd6 1264 propValue[valLen] = '\0';
XinZhangMS 0:f7f1f0d76dd6 1265
XinZhangMS 0:f7f1f0d76dd6 1266 if (urldecode)
XinZhangMS 0:f7f1f0d76dd6 1267 {
XinZhangMS 0:f7f1f0d76dd6 1268 STRING_HANDLE propValue_decoded;
XinZhangMS 0:f7f1f0d76dd6 1269 if ((propValue_decoded = URL_DecodeString(propValue)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1270 {
XinZhangMS 0:f7f1f0d76dd6 1271 LogError("Failed to URL decode property value");
XinZhangMS 0:f7f1f0d76dd6 1272 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1273 }
XinZhangMS 0:f7f1f0d76dd6 1274 else if (setMqttMessagePropertyIfPossible(IoTHubMessage, propName, STRING_c_str(propValue_decoded), nameLen) != 0)
XinZhangMS 0:f7f1f0d76dd6 1275 {
XinZhangMS 0:f7f1f0d76dd6 1276 LogError("Unable to set message property");
XinZhangMS 0:f7f1f0d76dd6 1277 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1278 }
XinZhangMS 0:f7f1f0d76dd6 1279 STRING_delete(propValue_decoded);
XinZhangMS 0:f7f1f0d76dd6 1280 }
XinZhangMS 0:f7f1f0d76dd6 1281 else
XinZhangMS 0:f7f1f0d76dd6 1282 {
XinZhangMS 0:f7f1f0d76dd6 1283 if (setMqttMessagePropertyIfPossible(IoTHubMessage, propName, propValue, nameLen) != 0)
XinZhangMS 0:f7f1f0d76dd6 1284 {
XinZhangMS 0:f7f1f0d76dd6 1285 LogError("Unable to set message property");
XinZhangMS 0:f7f1f0d76dd6 1286 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1287 }
XinZhangMS 0:f7f1f0d76dd6 1288 }
XinZhangMS 0:f7f1f0d76dd6 1289 }
XinZhangMS 0:f7f1f0d76dd6 1290 free(propName);
XinZhangMS 0:f7f1f0d76dd6 1291 free(propValue);
XinZhangMS 0:f7f1f0d76dd6 1292
XinZhangMS 0:f7f1f0d76dd6 1293 break;
XinZhangMS 0:f7f1f0d76dd6 1294 }
XinZhangMS 0:f7f1f0d76dd6 1295 iterator++;
XinZhangMS 0:f7f1f0d76dd6 1296 }
XinZhangMS 0:f7f1f0d76dd6 1297 }
XinZhangMS 0:f7f1f0d76dd6 1298 else //User Properties
XinZhangMS 0:f7f1f0d76dd6 1299 {
XinZhangMS 0:f7f1f0d76dd6 1300 const char* iterator = tokenData;
XinZhangMS 0:f7f1f0d76dd6 1301 while (iterator != NULL && *iterator != '\0' && result == 0)
XinZhangMS 0:f7f1f0d76dd6 1302 {
XinZhangMS 0:f7f1f0d76dd6 1303 if (*iterator == '=')
XinZhangMS 0:f7f1f0d76dd6 1304 {
XinZhangMS 0:f7f1f0d76dd6 1305 size_t nameLen = iterator - tokenData;
XinZhangMS 0:f7f1f0d76dd6 1306 char* propName = malloc(nameLen + 1);
XinZhangMS 0:f7f1f0d76dd6 1307
XinZhangMS 0:f7f1f0d76dd6 1308 size_t valLen = tokenLen - (nameLen + 1) + 1;
XinZhangMS 0:f7f1f0d76dd6 1309 char* propValue = malloc(valLen + 1);
XinZhangMS 0:f7f1f0d76dd6 1310
XinZhangMS 0:f7f1f0d76dd6 1311 if (propName == NULL || propValue == NULL)
XinZhangMS 0:f7f1f0d76dd6 1312 {
XinZhangMS 0:f7f1f0d76dd6 1313 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1314 }
XinZhangMS 0:f7f1f0d76dd6 1315 else
XinZhangMS 0:f7f1f0d76dd6 1316 {
XinZhangMS 0:f7f1f0d76dd6 1317 strncpy(propName, tokenData, nameLen);
XinZhangMS 0:f7f1f0d76dd6 1318 propName[nameLen] = '\0';
XinZhangMS 0:f7f1f0d76dd6 1319
XinZhangMS 0:f7f1f0d76dd6 1320 strncpy(propValue, iterator + 1, valLen);
XinZhangMS 0:f7f1f0d76dd6 1321 propValue[valLen] = '\0';
XinZhangMS 0:f7f1f0d76dd6 1322
XinZhangMS 0:f7f1f0d76dd6 1323 if (urldecode)
XinZhangMS 0:f7f1f0d76dd6 1324 {
XinZhangMS 0:f7f1f0d76dd6 1325 STRING_HANDLE propName_decoded = URL_DecodeString(propName);
XinZhangMS 0:f7f1f0d76dd6 1326 STRING_HANDLE propValue_decoded = URL_DecodeString(propValue);
XinZhangMS 0:f7f1f0d76dd6 1327 if (propName_decoded == NULL || propValue_decoded == NULL)
XinZhangMS 0:f7f1f0d76dd6 1328 {
XinZhangMS 0:f7f1f0d76dd6 1329 LogError("Failed to URL decode property");
XinZhangMS 0:f7f1f0d76dd6 1330 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1331 }
XinZhangMS 0:f7f1f0d76dd6 1332 else if (Map_AddOrUpdate(propertyMap, STRING_c_str(propName_decoded), STRING_c_str(propValue_decoded)) != MAP_OK)
XinZhangMS 0:f7f1f0d76dd6 1333 {
XinZhangMS 0:f7f1f0d76dd6 1334 LogError("Map_AddOrUpdate failed.");
XinZhangMS 0:f7f1f0d76dd6 1335 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1336 }
XinZhangMS 0:f7f1f0d76dd6 1337 STRING_delete(propName_decoded);
XinZhangMS 0:f7f1f0d76dd6 1338 STRING_delete(propValue_decoded);
XinZhangMS 0:f7f1f0d76dd6 1339 }
XinZhangMS 0:f7f1f0d76dd6 1340 else
XinZhangMS 0:f7f1f0d76dd6 1341 {
XinZhangMS 0:f7f1f0d76dd6 1342 if (Map_AddOrUpdate(propertyMap, propName, propValue) != MAP_OK)
XinZhangMS 0:f7f1f0d76dd6 1343 {
XinZhangMS 0:f7f1f0d76dd6 1344 LogError("Map_AddOrUpdate failed.");
XinZhangMS 0:f7f1f0d76dd6 1345 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1346 }
XinZhangMS 0:f7f1f0d76dd6 1347 }
XinZhangMS 0:f7f1f0d76dd6 1348 }
XinZhangMS 0:f7f1f0d76dd6 1349 free(propName);
XinZhangMS 0:f7f1f0d76dd6 1350 free(propValue);
XinZhangMS 0:f7f1f0d76dd6 1351
XinZhangMS 0:f7f1f0d76dd6 1352 break;
XinZhangMS 0:f7f1f0d76dd6 1353 }
XinZhangMS 0:f7f1f0d76dd6 1354 iterator++;
XinZhangMS 0:f7f1f0d76dd6 1355 }
XinZhangMS 0:f7f1f0d76dd6 1356 }
XinZhangMS 0:f7f1f0d76dd6 1357 }
XinZhangMS 0:f7f1f0d76dd6 1358 }
XinZhangMS 0:f7f1f0d76dd6 1359 STRING_delete(output);
XinZhangMS 0:f7f1f0d76dd6 1360 }
XinZhangMS 0:f7f1f0d76dd6 1361 }
XinZhangMS 0:f7f1f0d76dd6 1362 STRING_TOKENIZER_destroy(token);
XinZhangMS 0:f7f1f0d76dd6 1363 }
XinZhangMS 0:f7f1f0d76dd6 1364 else
XinZhangMS 0:f7f1f0d76dd6 1365 {
XinZhangMS 0:f7f1f0d76dd6 1366 LogError("Unable to create Tokenizer object.");
XinZhangMS 0:f7f1f0d76dd6 1367 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1368 }
XinZhangMS 0:f7f1f0d76dd6 1369 STRING_delete(mqttTopic);
XinZhangMS 0:f7f1f0d76dd6 1370 }
XinZhangMS 0:f7f1f0d76dd6 1371 return result;
XinZhangMS 0:f7f1f0d76dd6 1372 }
XinZhangMS 0:f7f1f0d76dd6 1373
XinZhangMS 0:f7f1f0d76dd6 1374 static void mqtt_notification_callback(MQTT_MESSAGE_HANDLE msgHandle, void* callbackCtx)
XinZhangMS 0:f7f1f0d76dd6 1375 {
XinZhangMS 0:f7f1f0d76dd6 1376 /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_051: [ If msgHandle or callbackCtx is NULL, mqtt_notification_callback shall do nothing. ] */
XinZhangMS 0:f7f1f0d76dd6 1377 if (msgHandle != NULL && callbackCtx != NULL)
XinZhangMS 0:f7f1f0d76dd6 1378 {
XinZhangMS 0:f7f1f0d76dd6 1379 /* Tests_SRS_IOTHUB_MQTT_TRANSPORT_07_052: [ mqtt_notification_callback shall extract the topic Name from the MQTT_MESSAGE_HANDLE. ] */
XinZhangMS 0:f7f1f0d76dd6 1380 const char* topic_resp = mqttmessage_getTopicName(msgHandle);
XinZhangMS 0:f7f1f0d76dd6 1381 if (topic_resp == NULL)
XinZhangMS 0:f7f1f0d76dd6 1382 {
XinZhangMS 0:f7f1f0d76dd6 1383 LogError("Failure: NULL topic name encountered");
XinZhangMS 0:f7f1f0d76dd6 1384 }
XinZhangMS 0:f7f1f0d76dd6 1385 else
XinZhangMS 0:f7f1f0d76dd6 1386 {
XinZhangMS 0:f7f1f0d76dd6 1387 PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
XinZhangMS 0:f7f1f0d76dd6 1388
XinZhangMS 0:f7f1f0d76dd6 1389 IOTHUB_IDENTITY_TYPE type = retrieve_topic_type(topic_resp, STRING_c_str(transportData->topic_InputQueue));
XinZhangMS 0:f7f1f0d76dd6 1390 if (type == IOTHUB_TYPE_DEVICE_TWIN)
XinZhangMS 0:f7f1f0d76dd6 1391 {
XinZhangMS 0:f7f1f0d76dd6 1392 size_t request_id;
XinZhangMS 0:f7f1f0d76dd6 1393 int status_code;
XinZhangMS 0:f7f1f0d76dd6 1394 bool notification_msg;
XinZhangMS 0:f7f1f0d76dd6 1395 if (parse_device_twin_topic_info(topic_resp, &notification_msg, &request_id, &status_code) != 0)
XinZhangMS 0:f7f1f0d76dd6 1396 {
XinZhangMS 0:f7f1f0d76dd6 1397 LogError("Failure: parsing device topic info");
XinZhangMS 0:f7f1f0d76dd6 1398 }
XinZhangMS 0:f7f1f0d76dd6 1399 else
XinZhangMS 0:f7f1f0d76dd6 1400 {
XinZhangMS 0:f7f1f0d76dd6 1401 const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
XinZhangMS 0:f7f1f0d76dd6 1402 if (notification_msg)
XinZhangMS 0:f7f1f0d76dd6 1403 {
XinZhangMS 0:f7f1f0d76dd6 1404 IoTHubClientCore_LL_RetrievePropertyComplete(transportData->llClientHandle, DEVICE_TWIN_UPDATE_PARTIAL, payload->message, payload->length);
XinZhangMS 0:f7f1f0d76dd6 1405 }
XinZhangMS 0:f7f1f0d76dd6 1406 else
XinZhangMS 0:f7f1f0d76dd6 1407 {
XinZhangMS 0:f7f1f0d76dd6 1408 PDLIST_ENTRY dev_twin_item = transportData->ack_waiting_queue.Flink;
XinZhangMS 0:f7f1f0d76dd6 1409 while (dev_twin_item != &transportData->ack_waiting_queue)
XinZhangMS 0:f7f1f0d76dd6 1410 {
XinZhangMS 0:f7f1f0d76dd6 1411 DLIST_ENTRY saveListEntry;
XinZhangMS 0:f7f1f0d76dd6 1412 saveListEntry.Flink = dev_twin_item->Flink;
XinZhangMS 0:f7f1f0d76dd6 1413 MQTT_DEVICE_TWIN_ITEM* msg_entry = containingRecord(dev_twin_item, MQTT_DEVICE_TWIN_ITEM, entry);
XinZhangMS 0:f7f1f0d76dd6 1414 if (request_id == msg_entry->packet_id)
XinZhangMS 0:f7f1f0d76dd6 1415 {
XinZhangMS 0:f7f1f0d76dd6 1416 (void)DList_RemoveEntryList(dev_twin_item);
XinZhangMS 0:f7f1f0d76dd6 1417 if (msg_entry->device_twin_msg_type == RETRIEVE_PROPERTIES)
XinZhangMS 0:f7f1f0d76dd6 1418 {
XinZhangMS 0:f7f1f0d76dd6 1419 /* 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... ] */
XinZhangMS 0:f7f1f0d76dd6 1420 IoTHubClientCore_LL_RetrievePropertyComplete(transportData->llClientHandle, DEVICE_TWIN_UPDATE_COMPLETE, payload->message, payload->length);
XinZhangMS 0:f7f1f0d76dd6 1421 // Only after receiving device twin request should we start listening for patches.
XinZhangMS 0:f7f1f0d76dd6 1422 (void)subscribeToNotifyStateIfNeeded(transportData);
XinZhangMS 0:f7f1f0d76dd6 1423 }
XinZhangMS 0:f7f1f0d76dd6 1424 else
XinZhangMS 0:f7f1f0d76dd6 1425 {
XinZhangMS 0:f7f1f0d76dd6 1426 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ if device_twin_msg_type is not RETRIEVE_PROPERTIES then mqtt_notification_callback shall call IoTHubClientCore_LL_ReportedStateComplete ] */
XinZhangMS 0:f7f1f0d76dd6 1427 IoTHubClientCore_LL_ReportedStateComplete(transportData->llClientHandle, msg_entry->iothub_msg_id, status_code);
XinZhangMS 0:f7f1f0d76dd6 1428 }
XinZhangMS 0:f7f1f0d76dd6 1429 free(msg_entry);
XinZhangMS 0:f7f1f0d76dd6 1430 break;
XinZhangMS 0:f7f1f0d76dd6 1431 }
XinZhangMS 0:f7f1f0d76dd6 1432 dev_twin_item = saveListEntry.Flink;
XinZhangMS 0:f7f1f0d76dd6 1433 }
XinZhangMS 0:f7f1f0d76dd6 1434 }
XinZhangMS 0:f7f1f0d76dd6 1435 }
XinZhangMS 0:f7f1f0d76dd6 1436 }
XinZhangMS 0:f7f1f0d76dd6 1437 else if (type == IOTHUB_TYPE_DEVICE_METHODS)
XinZhangMS 0:f7f1f0d76dd6 1438 {
XinZhangMS 0:f7f1f0d76dd6 1439 STRING_HANDLE method_name = STRING_new();
XinZhangMS 0:f7f1f0d76dd6 1440 if (method_name == NULL)
XinZhangMS 0:f7f1f0d76dd6 1441 {
XinZhangMS 0:f7f1f0d76dd6 1442 LogError("Failure: allocating method_name string value");
XinZhangMS 0:f7f1f0d76dd6 1443 }
XinZhangMS 0:f7f1f0d76dd6 1444 else
XinZhangMS 0:f7f1f0d76dd6 1445 {
XinZhangMS 0:f7f1f0d76dd6 1446 DEVICE_METHOD_INFO* dev_method_info = malloc(sizeof(DEVICE_METHOD_INFO));
XinZhangMS 0:f7f1f0d76dd6 1447 if (dev_method_info == NULL)
XinZhangMS 0:f7f1f0d76dd6 1448 {
XinZhangMS 0:f7f1f0d76dd6 1449 LogError("Failure: allocating DEVICE_METHOD_INFO object");
XinZhangMS 0:f7f1f0d76dd6 1450 }
XinZhangMS 0:f7f1f0d76dd6 1451 else
XinZhangMS 0:f7f1f0d76dd6 1452 {
XinZhangMS 0:f7f1f0d76dd6 1453 dev_method_info->request_id = STRING_new();
XinZhangMS 0:f7f1f0d76dd6 1454 if (dev_method_info->request_id == NULL)
XinZhangMS 0:f7f1f0d76dd6 1455 {
XinZhangMS 0:f7f1f0d76dd6 1456 LogError("Failure constructing request_id string");
XinZhangMS 0:f7f1f0d76dd6 1457 free(dev_method_info);
XinZhangMS 0:f7f1f0d76dd6 1458 }
XinZhangMS 0:f7f1f0d76dd6 1459 else if (retrieve_device_method_rid_info(topic_resp, method_name, dev_method_info->request_id) != 0)
XinZhangMS 0:f7f1f0d76dd6 1460 {
XinZhangMS 0:f7f1f0d76dd6 1461 LogError("Failure: retrieve device topic info");
XinZhangMS 0:f7f1f0d76dd6 1462 STRING_delete(dev_method_info->request_id);
XinZhangMS 0:f7f1f0d76dd6 1463 free(dev_method_info);
XinZhangMS 0:f7f1f0d76dd6 1464 }
XinZhangMS 0:f7f1f0d76dd6 1465 else
XinZhangMS 0:f7f1f0d76dd6 1466 {
XinZhangMS 0:f7f1f0d76dd6 1467 /* CodesSRS_IOTHUB_MQTT_TRANSPORT_07_053: [ If type is IOTHUB_TYPE_DEVICE_METHODS, then on success mqtt_notification_callback shall call IoTHubClientCore_LL_DeviceMethodComplete. ] */
XinZhangMS 0:f7f1f0d76dd6 1468 const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
XinZhangMS 0:f7f1f0d76dd6 1469 if (IoTHubClientCore_LL_DeviceMethodComplete(transportData->llClientHandle, STRING_c_str(method_name), payload->message, payload->length, (void*)dev_method_info) != 0)
XinZhangMS 0:f7f1f0d76dd6 1470 {
XinZhangMS 0:f7f1f0d76dd6 1471 LogError("Failure: IoTHubClientCore_LL_DeviceMethodComplete");
XinZhangMS 0:f7f1f0d76dd6 1472 STRING_delete(dev_method_info->request_id);
XinZhangMS 0:f7f1f0d76dd6 1473 free(dev_method_info);
XinZhangMS 0:f7f1f0d76dd6 1474 }
XinZhangMS 0:f7f1f0d76dd6 1475 }
XinZhangMS 0:f7f1f0d76dd6 1476 }
XinZhangMS 0:f7f1f0d76dd6 1477 STRING_delete(method_name);
XinZhangMS 0:f7f1f0d76dd6 1478 }
XinZhangMS 0:f7f1f0d76dd6 1479 }
XinZhangMS 0:f7f1f0d76dd6 1480 else
XinZhangMS 0:f7f1f0d76dd6 1481 {
XinZhangMS 0:f7f1f0d76dd6 1482 const APP_PAYLOAD* appPayload = mqttmessage_getApplicationMsg(msgHandle);
XinZhangMS 0:f7f1f0d76dd6 1483 IOTHUB_MESSAGE_HANDLE IoTHubMessage = IoTHubMessage_CreateFromByteArray(appPayload->message, appPayload->length);
XinZhangMS 0:f7f1f0d76dd6 1484 if (IoTHubMessage == NULL)
XinZhangMS 0:f7f1f0d76dd6 1485 {
XinZhangMS 0:f7f1f0d76dd6 1486 LogError("Failure: IotHub Message creation has failed.");
XinZhangMS 0:f7f1f0d76dd6 1487 }
XinZhangMS 0:f7f1f0d76dd6 1488 else
XinZhangMS 0:f7f1f0d76dd6 1489 {
XinZhangMS 0:f7f1f0d76dd6 1490 if ((type == IOTHUB_TYPE_EVENT_QUEUE) && (addInputNamePropertyToMessage(IoTHubMessage, topic_resp) != 0))
XinZhangMS 0:f7f1f0d76dd6 1491 {
XinZhangMS 0:f7f1f0d76dd6 1492 LogError("failure adding input name to property.");
XinZhangMS 0:f7f1f0d76dd6 1493 }
XinZhangMS 0:f7f1f0d76dd6 1494 // Will need to update this when the service has messages that can be rejected
XinZhangMS 0:f7f1f0d76dd6 1495 else if (extractMqttProperties(IoTHubMessage, topic_resp, transportData->auto_url_encode_decode) != 0)
XinZhangMS 0:f7f1f0d76dd6 1496 {
XinZhangMS 0:f7f1f0d76dd6 1497 LogError("failure extracting mqtt properties.");
XinZhangMS 0:f7f1f0d76dd6 1498 }
XinZhangMS 0:f7f1f0d76dd6 1499 else
XinZhangMS 0:f7f1f0d76dd6 1500 {
XinZhangMS 0:f7f1f0d76dd6 1501 MESSAGE_CALLBACK_INFO* messageData = (MESSAGE_CALLBACK_INFO*)malloc(sizeof(MESSAGE_CALLBACK_INFO));
XinZhangMS 0:f7f1f0d76dd6 1502 if (messageData == NULL)
XinZhangMS 0:f7f1f0d76dd6 1503 {
XinZhangMS 0:f7f1f0d76dd6 1504 LogError("malloc failed");
XinZhangMS 0:f7f1f0d76dd6 1505 }
XinZhangMS 0:f7f1f0d76dd6 1506 else
XinZhangMS 0:f7f1f0d76dd6 1507 {
XinZhangMS 0:f7f1f0d76dd6 1508 messageData->messageHandle = IoTHubMessage;
XinZhangMS 0:f7f1f0d76dd6 1509 messageData->transportContext = NULL;
XinZhangMS 0:f7f1f0d76dd6 1510
XinZhangMS 0:f7f1f0d76dd6 1511 if (type == IOTHUB_TYPE_EVENT_QUEUE)
XinZhangMS 0:f7f1f0d76dd6 1512 {
XinZhangMS 0:f7f1f0d76dd6 1513 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_31_065: [ If type is IOTHUB_TYPE_TELEMETRY and sent to an input queue, then on success `mqtt_notification_callback` shall call `IoTHubClient_LL_MessageCallback`. ]
XinZhangMS 0:f7f1f0d76dd6 1514 if (!IoTHubClientCore_LL_MessageCallbackFromInput(transportData->llClientHandle, messageData))
XinZhangMS 0:f7f1f0d76dd6 1515 {
XinZhangMS 0:f7f1f0d76dd6 1516 LogError("IoTHubClientCore_LL_MessageCallbackreturned false");
XinZhangMS 0:f7f1f0d76dd6 1517
XinZhangMS 0:f7f1f0d76dd6 1518 IoTHubMessage_Destroy(IoTHubMessage);
XinZhangMS 0:f7f1f0d76dd6 1519 free(messageData);
XinZhangMS 0:f7f1f0d76dd6 1520 }
XinZhangMS 0:f7f1f0d76dd6 1521 }
XinZhangMS 0:f7f1f0d76dd6 1522 else
XinZhangMS 0:f7f1f0d76dd6 1523 {
XinZhangMS 0:f7f1f0d76dd6 1524 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_056: [ If type is IOTHUB_TYPE_TELEMETRY, then on success mqtt_notification_callback shall call IoTHubClientCore_LL_MessageCallback. ] */
XinZhangMS 0:f7f1f0d76dd6 1525 if (!IoTHubClientCore_LL_MessageCallback(transportData->llClientHandle, messageData))
XinZhangMS 0:f7f1f0d76dd6 1526 {
XinZhangMS 0:f7f1f0d76dd6 1527 LogError("IoTHubClientCore_LL_MessageCallback returned false");
XinZhangMS 0:f7f1f0d76dd6 1528 IoTHubMessage_Destroy(IoTHubMessage);
XinZhangMS 0:f7f1f0d76dd6 1529 free(messageData);
XinZhangMS 0:f7f1f0d76dd6 1530 }
XinZhangMS 0:f7f1f0d76dd6 1531 }
XinZhangMS 0:f7f1f0d76dd6 1532 }
XinZhangMS 0:f7f1f0d76dd6 1533 }
XinZhangMS 0:f7f1f0d76dd6 1534 }
XinZhangMS 0:f7f1f0d76dd6 1535 }
XinZhangMS 0:f7f1f0d76dd6 1536 }
XinZhangMS 0:f7f1f0d76dd6 1537 }
XinZhangMS 0:f7f1f0d76dd6 1538 }
XinZhangMS 0:f7f1f0d76dd6 1539
XinZhangMS 0:f7f1f0d76dd6 1540 static void mqtt_operation_complete_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx)
XinZhangMS 0:f7f1f0d76dd6 1541 {
XinZhangMS 0:f7f1f0d76dd6 1542 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 1543 if (callbackCtx != NULL)
XinZhangMS 0:f7f1f0d76dd6 1544 {
XinZhangMS 0:f7f1f0d76dd6 1545 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
XinZhangMS 0:f7f1f0d76dd6 1546
XinZhangMS 0:f7f1f0d76dd6 1547 switch (actionResult)
XinZhangMS 0:f7f1f0d76dd6 1548 {
XinZhangMS 0:f7f1f0d76dd6 1549 case MQTT_CLIENT_ON_PUBLISH_ACK:
XinZhangMS 0:f7f1f0d76dd6 1550 case MQTT_CLIENT_ON_PUBLISH_COMP:
XinZhangMS 0:f7f1f0d76dd6 1551 {
XinZhangMS 0:f7f1f0d76dd6 1552 const PUBLISH_ACK* puback = (const PUBLISH_ACK*)msgInfo;
XinZhangMS 0:f7f1f0d76dd6 1553 if (puback != NULL)
XinZhangMS 0:f7f1f0d76dd6 1554 {
XinZhangMS 0:f7f1f0d76dd6 1555 PDLIST_ENTRY currentListEntry = transport_data->telemetry_waitingForAck.Flink;
XinZhangMS 0:f7f1f0d76dd6 1556 while (currentListEntry != &transport_data->telemetry_waitingForAck)
XinZhangMS 0:f7f1f0d76dd6 1557 {
XinZhangMS 0:f7f1f0d76dd6 1558 MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentListEntry, MQTT_MESSAGE_DETAILS_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 1559 DLIST_ENTRY saveListEntry;
XinZhangMS 0:f7f1f0d76dd6 1560 saveListEntry.Flink = currentListEntry->Flink;
XinZhangMS 0:f7f1f0d76dd6 1561
XinZhangMS 0:f7f1f0d76dd6 1562 if (puback->packetId == mqttMsgEntry->packet_id)
XinZhangMS 0:f7f1f0d76dd6 1563 {
XinZhangMS 0:f7f1f0d76dd6 1564 (void)DList_RemoveEntryList(currentListEntry); //First remove the item from Waiting for Ack List.
XinZhangMS 0:f7f1f0d76dd6 1565 sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_OK);
XinZhangMS 0:f7f1f0d76dd6 1566 free(mqttMsgEntry);
XinZhangMS 0:f7f1f0d76dd6 1567 }
XinZhangMS 0:f7f1f0d76dd6 1568 currentListEntry = saveListEntry.Flink;
XinZhangMS 0:f7f1f0d76dd6 1569 }
XinZhangMS 0:f7f1f0d76dd6 1570 }
XinZhangMS 0:f7f1f0d76dd6 1571 else
XinZhangMS 0:f7f1f0d76dd6 1572 {
XinZhangMS 0:f7f1f0d76dd6 1573 LogError("Failure: MQTT_CLIENT_ON_PUBLISH_ACK publish_ack structure NULL.");
XinZhangMS 0:f7f1f0d76dd6 1574 }
XinZhangMS 0:f7f1f0d76dd6 1575 break;
XinZhangMS 0:f7f1f0d76dd6 1576 }
XinZhangMS 0:f7f1f0d76dd6 1577 case MQTT_CLIENT_ON_CONNACK:
XinZhangMS 0:f7f1f0d76dd6 1578 {
XinZhangMS 0:f7f1f0d76dd6 1579 const CONNECT_ACK* connack = (const CONNECT_ACK*)msgInfo;
XinZhangMS 0:f7f1f0d76dd6 1580 if (connack != NULL)
XinZhangMS 0:f7f1f0d76dd6 1581 {
XinZhangMS 0:f7f1f0d76dd6 1582 if (connack->returnCode == CONNECTION_ACCEPTED)
XinZhangMS 0:f7f1f0d76dd6 1583 {
XinZhangMS 0:f7f1f0d76dd6 1584 // The connect packet has been acked
XinZhangMS 0:f7f1f0d76dd6 1585 transport_data->currPacketState = CONNACK_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1586 transport_data->isRecoverableError = true;
XinZhangMS 0:f7f1f0d76dd6 1587 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 1588
XinZhangMS 0:f7f1f0d76dd6 1589 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_008: [ Upon successful connection the retry control shall be reset using retry_control_reset() ]
XinZhangMS 0:f7f1f0d76dd6 1590 retry_control_reset(transport_data->retry_control_handle);
XinZhangMS 0:f7f1f0d76dd6 1591
XinZhangMS 0:f7f1f0d76dd6 1592 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_AUTHENTICATED, IOTHUB_CLIENT_CONNECTION_OK);
XinZhangMS 0:f7f1f0d76dd6 1593 }
XinZhangMS 0:f7f1f0d76dd6 1594 else
XinZhangMS 0:f7f1f0d76dd6 1595 {
XinZhangMS 0:f7f1f0d76dd6 1596 if (connack->returnCode == CONN_REFUSED_SERVER_UNAVAIL)
XinZhangMS 0:f7f1f0d76dd6 1597 {
XinZhangMS 0:f7f1f0d76dd6 1598 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_DEVICE_DISABLED);
XinZhangMS 0:f7f1f0d76dd6 1599 }
XinZhangMS 0:f7f1f0d76dd6 1600 else if (connack->returnCode == CONN_REFUSED_BAD_USERNAME_PASSWORD || connack->returnCode == CONN_REFUSED_ID_REJECTED)
XinZhangMS 0:f7f1f0d76dd6 1601 {
XinZhangMS 0:f7f1f0d76dd6 1602 transport_data->isRecoverableError = false;
XinZhangMS 0:f7f1f0d76dd6 1603 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL);
XinZhangMS 0:f7f1f0d76dd6 1604 }
XinZhangMS 0:f7f1f0d76dd6 1605 else if (connack->returnCode == CONN_REFUSED_NOT_AUTHORIZED)
XinZhangMS 0:f7f1f0d76dd6 1606 {
XinZhangMS 0:f7f1f0d76dd6 1607 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_DEVICE_DISABLED);
XinZhangMS 0:f7f1f0d76dd6 1608 }
XinZhangMS 0:f7f1f0d76dd6 1609 else if (connack->returnCode == CONN_REFUSED_UNACCEPTABLE_VERSION)
XinZhangMS 0:f7f1f0d76dd6 1610 {
XinZhangMS 0:f7f1f0d76dd6 1611 transport_data->isRecoverableError = false;
XinZhangMS 0:f7f1f0d76dd6 1612 }
XinZhangMS 0:f7f1f0d76dd6 1613 LogError("Connection Not Accepted: 0x%x: %s", connack->returnCode, retrieve_mqtt_return_codes(connack->returnCode));
XinZhangMS 0:f7f1f0d76dd6 1614 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_PENDING_CLOSE;
XinZhangMS 0:f7f1f0d76dd6 1615 transport_data->currPacketState = PACKET_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1616 }
XinZhangMS 0:f7f1f0d76dd6 1617 }
XinZhangMS 0:f7f1f0d76dd6 1618 else
XinZhangMS 0:f7f1f0d76dd6 1619 {
XinZhangMS 0:f7f1f0d76dd6 1620 LogError("MQTT_CLIENT_ON_CONNACK CONNACK parameter is NULL.");
XinZhangMS 0:f7f1f0d76dd6 1621 }
XinZhangMS 0:f7f1f0d76dd6 1622 break;
XinZhangMS 0:f7f1f0d76dd6 1623 }
XinZhangMS 0:f7f1f0d76dd6 1624 case MQTT_CLIENT_ON_SUBSCRIBE_ACK:
XinZhangMS 0:f7f1f0d76dd6 1625 {
XinZhangMS 0:f7f1f0d76dd6 1626 const SUBSCRIBE_ACK* suback = (const SUBSCRIBE_ACK*)msgInfo;
XinZhangMS 0:f7f1f0d76dd6 1627 if (suback != NULL)
XinZhangMS 0:f7f1f0d76dd6 1628 {
XinZhangMS 0:f7f1f0d76dd6 1629 size_t index = 0;
XinZhangMS 0:f7f1f0d76dd6 1630 for (index = 0; index < suback->qosCount; index++)
XinZhangMS 0:f7f1f0d76dd6 1631 {
XinZhangMS 0:f7f1f0d76dd6 1632 if (suback->qosReturn[index] == DELIVER_FAILURE)
XinZhangMS 0:f7f1f0d76dd6 1633 {
XinZhangMS 0:f7f1f0d76dd6 1634 LogError("Subscribe delivery failure of subscribe %lu", index);
XinZhangMS 0:f7f1f0d76dd6 1635 }
XinZhangMS 0:f7f1f0d76dd6 1636 }
XinZhangMS 0:f7f1f0d76dd6 1637 // The connect packet has been acked
XinZhangMS 0:f7f1f0d76dd6 1638 transport_data->currPacketState = SUBACK_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1639 }
XinZhangMS 0:f7f1f0d76dd6 1640 else
XinZhangMS 0:f7f1f0d76dd6 1641 {
XinZhangMS 0:f7f1f0d76dd6 1642 LogError("Failure: MQTT_CLIENT_ON_SUBSCRIBE_ACK SUBSCRIBE_ACK parameter is NULL.");
XinZhangMS 0:f7f1f0d76dd6 1643 }
XinZhangMS 0:f7f1f0d76dd6 1644 break;
XinZhangMS 0:f7f1f0d76dd6 1645 }
XinZhangMS 0:f7f1f0d76dd6 1646 case MQTT_CLIENT_ON_PUBLISH_RECV:
XinZhangMS 0:f7f1f0d76dd6 1647 case MQTT_CLIENT_ON_PUBLISH_REL:
XinZhangMS 0:f7f1f0d76dd6 1648 {
XinZhangMS 0:f7f1f0d76dd6 1649 // Currently not used
XinZhangMS 0:f7f1f0d76dd6 1650 break;
XinZhangMS 0:f7f1f0d76dd6 1651 }
XinZhangMS 0:f7f1f0d76dd6 1652 case MQTT_CLIENT_ON_DISCONNECT:
XinZhangMS 0:f7f1f0d76dd6 1653 {
XinZhangMS 0:f7f1f0d76dd6 1654 // Close the client so we can reconnect again
XinZhangMS 0:f7f1f0d76dd6 1655 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 1656 transport_data->currPacketState = DISCONNECT_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1657 break;
XinZhangMS 0:f7f1f0d76dd6 1658 }
XinZhangMS 0:f7f1f0d76dd6 1659 case MQTT_CLIENT_ON_UNSUBSCRIBE_ACK:
XinZhangMS 0:f7f1f0d76dd6 1660 case MQTT_CLIENT_ON_PING_RESPONSE:
XinZhangMS 0:f7f1f0d76dd6 1661 default:
XinZhangMS 0:f7f1f0d76dd6 1662 {
XinZhangMS 0:f7f1f0d76dd6 1663 break;
XinZhangMS 0:f7f1f0d76dd6 1664 }
XinZhangMS 0:f7f1f0d76dd6 1665 }
XinZhangMS 0:f7f1f0d76dd6 1666 }
XinZhangMS 0:f7f1f0d76dd6 1667 }
XinZhangMS 0:f7f1f0d76dd6 1668
XinZhangMS 0:f7f1f0d76dd6 1669 // Prior to creating a new connection, if we have an existing xioTransport that has been connected before
XinZhangMS 0:f7f1f0d76dd6 1670 // we need to clear it now or else cached settings (especially TLS when communicating with HTTP proxies)
XinZhangMS 0:f7f1f0d76dd6 1671 // will break reconnection attempt.
XinZhangMS 0:f7f1f0d76dd6 1672 static void ResetConnectionIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1673 {
XinZhangMS 0:f7f1f0d76dd6 1674 if (transport_data->xioTransport != NULL && transport_data->conn_attempted)
XinZhangMS 0:f7f1f0d76dd6 1675 {
XinZhangMS 0:f7f1f0d76dd6 1676 OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
XinZhangMS 0:f7f1f0d76dd6 1677 set_saved_tls_options(transport_data, options);
XinZhangMS 0:f7f1f0d76dd6 1678
XinZhangMS 0:f7f1f0d76dd6 1679 xio_destroy(transport_data->xioTransport);
XinZhangMS 0:f7f1f0d76dd6 1680 transport_data->xioTransport = NULL;
XinZhangMS 0:f7f1f0d76dd6 1681 }
XinZhangMS 0:f7f1f0d76dd6 1682 }
XinZhangMS 0:f7f1f0d76dd6 1683
XinZhangMS 0:f7f1f0d76dd6 1684 static void DisconnectFromClient(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1685 {
XinZhangMS 0:f7f1f0d76dd6 1686 if (!transport_data->isDestroyCalled)
XinZhangMS 0:f7f1f0d76dd6 1687 {
XinZhangMS 0:f7f1f0d76dd6 1688 OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
XinZhangMS 0:f7f1f0d76dd6 1689 set_saved_tls_options(transport_data, options);
XinZhangMS 0:f7f1f0d76dd6 1690 }
XinZhangMS 0:f7f1f0d76dd6 1691
XinZhangMS 0:f7f1f0d76dd6 1692 (void)mqtt_client_disconnect(transport_data->mqttClient, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 1693 xio_destroy(transport_data->xioTransport);
XinZhangMS 0:f7f1f0d76dd6 1694 transport_data->xioTransport = NULL;
XinZhangMS 0:f7f1f0d76dd6 1695
XinZhangMS 0:f7f1f0d76dd6 1696 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 1697 transport_data->currPacketState = DISCONNECT_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1698 }
XinZhangMS 0:f7f1f0d76dd6 1699
XinZhangMS 0:f7f1f0d76dd6 1700 static void mqtt_error_callback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_ERROR error, void* callbackCtx)
XinZhangMS 0:f7f1f0d76dd6 1701 {
XinZhangMS 0:f7f1f0d76dd6 1702 (void)handle;
XinZhangMS 0:f7f1f0d76dd6 1703 if (callbackCtx != NULL)
XinZhangMS 0:f7f1f0d76dd6 1704 {
XinZhangMS 0:f7f1f0d76dd6 1705 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx;
XinZhangMS 0:f7f1f0d76dd6 1706 switch (error)
XinZhangMS 0:f7f1f0d76dd6 1707 {
XinZhangMS 0:f7f1f0d76dd6 1708 case MQTT_CLIENT_CONNECTION_ERROR:
XinZhangMS 0:f7f1f0d76dd6 1709 {
XinZhangMS 0:f7f1f0d76dd6 1710 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_NO_NETWORK);
XinZhangMS 0:f7f1f0d76dd6 1711 break;
XinZhangMS 0:f7f1f0d76dd6 1712 }
XinZhangMS 0:f7f1f0d76dd6 1713 case MQTT_CLIENT_COMMUNICATION_ERROR:
XinZhangMS 0:f7f1f0d76dd6 1714 {
XinZhangMS 0:f7f1f0d76dd6 1715 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR);
XinZhangMS 0:f7f1f0d76dd6 1716 break;
XinZhangMS 0:f7f1f0d76dd6 1717 }
XinZhangMS 0:f7f1f0d76dd6 1718 case MQTT_CLIENT_NO_PING_RESPONSE:
XinZhangMS 0:f7f1f0d76dd6 1719 {
XinZhangMS 0:f7f1f0d76dd6 1720 LogError("Mqtt Ping Response was not encountered. Reconnecting device...");
XinZhangMS 0:f7f1f0d76dd6 1721 DisconnectFromClient(transport_data);
XinZhangMS 0:f7f1f0d76dd6 1722 break;
XinZhangMS 0:f7f1f0d76dd6 1723 }
XinZhangMS 0:f7f1f0d76dd6 1724 case MQTT_CLIENT_PARSE_ERROR:
XinZhangMS 0:f7f1f0d76dd6 1725 case MQTT_CLIENT_MEMORY_ERROR:
XinZhangMS 0:f7f1f0d76dd6 1726 case MQTT_CLIENT_UNKNOWN_ERROR:
XinZhangMS 0:f7f1f0d76dd6 1727 {
XinZhangMS 0:f7f1f0d76dd6 1728 LogError("INTERNAL ERROR: unexpected error value received %s", ENUM_TO_STRING(MQTT_CLIENT_EVENT_ERROR, error));
XinZhangMS 0:f7f1f0d76dd6 1729 break;
XinZhangMS 0:f7f1f0d76dd6 1730 }
XinZhangMS 0:f7f1f0d76dd6 1731 }
XinZhangMS 0:f7f1f0d76dd6 1732 if (transport_data->mqttClientStatus != MQTT_CLIENT_STATUS_PENDING_CLOSE)
XinZhangMS 0:f7f1f0d76dd6 1733 {
XinZhangMS 0:f7f1f0d76dd6 1734 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 1735 }
XinZhangMS 0:f7f1f0d76dd6 1736 transport_data->currPacketState = PACKET_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 1737 transport_data->device_twin_get_sent = false;
XinZhangMS 0:f7f1f0d76dd6 1738 if (transport_data->topic_MqttMessage != NULL)
XinZhangMS 0:f7f1f0d76dd6 1739 {
XinZhangMS 0:f7f1f0d76dd6 1740 transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1741 }
XinZhangMS 0:f7f1f0d76dd6 1742 if (transport_data->topic_GetState != NULL)
XinZhangMS 0:f7f1f0d76dd6 1743 {
XinZhangMS 0:f7f1f0d76dd6 1744 transport_data->topics_ToSubscribe |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1745 }
XinZhangMS 0:f7f1f0d76dd6 1746 if (transport_data->topic_NotifyState != NULL)
XinZhangMS 0:f7f1f0d76dd6 1747 {
XinZhangMS 0:f7f1f0d76dd6 1748 transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1749 }
XinZhangMS 0:f7f1f0d76dd6 1750 if (transport_data->topic_DeviceMethods != NULL)
XinZhangMS 0:f7f1f0d76dd6 1751 {
XinZhangMS 0:f7f1f0d76dd6 1752 transport_data->topics_ToSubscribe |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1753 }
XinZhangMS 0:f7f1f0d76dd6 1754 if (transport_data->topic_InputQueue != NULL)
XinZhangMS 0:f7f1f0d76dd6 1755 {
XinZhangMS 0:f7f1f0d76dd6 1756 transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1757 }
XinZhangMS 0:f7f1f0d76dd6 1758 }
XinZhangMS 0:f7f1f0d76dd6 1759 else
XinZhangMS 0:f7f1f0d76dd6 1760 {
XinZhangMS 0:f7f1f0d76dd6 1761 LogError("Failure: mqtt called back with null context.");
XinZhangMS 0:f7f1f0d76dd6 1762 }
XinZhangMS 0:f7f1f0d76dd6 1763 }
XinZhangMS 0:f7f1f0d76dd6 1764
XinZhangMS 0:f7f1f0d76dd6 1765 static void SubscribeToMqttProtocol(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1766 {
XinZhangMS 0:f7f1f0d76dd6 1767 if (transport_data->topics_ToSubscribe != UNSUBSCRIBE_FROM_TOPIC)
XinZhangMS 0:f7f1f0d76dd6 1768 {
XinZhangMS 0:f7f1f0d76dd6 1769 uint32_t topic_subscription = 0;
XinZhangMS 0:f7f1f0d76dd6 1770 size_t subscribe_count = 0;
XinZhangMS 0:f7f1f0d76dd6 1771 SUBSCRIBE_PAYLOAD subscribe[SUBSCRIBE_TOPIC_COUNT];
XinZhangMS 0:f7f1f0d76dd6 1772 if ((transport_data->topic_MqttMessage != NULL) && (SUBSCRIBE_TELEMETRY_TOPIC & transport_data->topics_ToSubscribe))
XinZhangMS 0:f7f1f0d76dd6 1773 {
XinZhangMS 0:f7f1f0d76dd6 1774 subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_MqttMessage);
XinZhangMS 0:f7f1f0d76dd6 1775 subscribe[subscribe_count].qosReturn = DELIVER_AT_LEAST_ONCE;
XinZhangMS 0:f7f1f0d76dd6 1776 topic_subscription |= SUBSCRIBE_TELEMETRY_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1777 subscribe_count++;
XinZhangMS 0:f7f1f0d76dd6 1778 }
XinZhangMS 0:f7f1f0d76dd6 1779 if ((transport_data->topic_GetState != NULL) && (SUBSCRIBE_GET_REPORTED_STATE_TOPIC & transport_data->topics_ToSubscribe))
XinZhangMS 0:f7f1f0d76dd6 1780 {
XinZhangMS 0:f7f1f0d76dd6 1781 subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_GetState);
XinZhangMS 0:f7f1f0d76dd6 1782 subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
XinZhangMS 0:f7f1f0d76dd6 1783 topic_subscription |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1784 subscribe_count++;
XinZhangMS 0:f7f1f0d76dd6 1785 }
XinZhangMS 0:f7f1f0d76dd6 1786 if ((transport_data->topic_NotifyState != NULL) && (SUBSCRIBE_NOTIFICATION_STATE_TOPIC & transport_data->topics_ToSubscribe))
XinZhangMS 0:f7f1f0d76dd6 1787 {
XinZhangMS 0:f7f1f0d76dd6 1788 subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_NotifyState);
XinZhangMS 0:f7f1f0d76dd6 1789 subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
XinZhangMS 0:f7f1f0d76dd6 1790 topic_subscription |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1791 subscribe_count++;
XinZhangMS 0:f7f1f0d76dd6 1792 }
XinZhangMS 0:f7f1f0d76dd6 1793 if ((transport_data->topic_DeviceMethods != NULL) && (SUBSCRIBE_DEVICE_METHOD_TOPIC & transport_data->topics_ToSubscribe))
XinZhangMS 0:f7f1f0d76dd6 1794 {
XinZhangMS 0:f7f1f0d76dd6 1795 subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_DeviceMethods);
XinZhangMS 0:f7f1f0d76dd6 1796 subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
XinZhangMS 0:f7f1f0d76dd6 1797 topic_subscription |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1798 subscribe_count++;
XinZhangMS 0:f7f1f0d76dd6 1799 }
XinZhangMS 0:f7f1f0d76dd6 1800 if ((transport_data->topic_InputQueue != NULL) && (SUBSCRIBE_INPUT_QUEUE_TOPIC & transport_data->topics_ToSubscribe))
XinZhangMS 0:f7f1f0d76dd6 1801 {
XinZhangMS 0:f7f1f0d76dd6 1802 subscribe[subscribe_count].subscribeTopic = STRING_c_str(transport_data->topic_InputQueue);
XinZhangMS 0:f7f1f0d76dd6 1803 subscribe[subscribe_count].qosReturn = DELIVER_AT_MOST_ONCE;
XinZhangMS 0:f7f1f0d76dd6 1804 topic_subscription |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 1805 subscribe_count++;
XinZhangMS 0:f7f1f0d76dd6 1806 }
XinZhangMS 0:f7f1f0d76dd6 1807
XinZhangMS 0:f7f1f0d76dd6 1808 if (subscribe_count != 0)
XinZhangMS 0:f7f1f0d76dd6 1809 {
XinZhangMS 0:f7f1f0d76dd6 1810 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_016: [IoTHubTransport_MQTT_Common_Subscribe shall call mqtt_client_subscribe to subscribe to the Message Topic.] */
XinZhangMS 0:f7f1f0d76dd6 1811 if (mqtt_client_subscribe(transport_data->mqttClient, get_next_packet_id(transport_data), subscribe, subscribe_count) != 0)
XinZhangMS 0:f7f1f0d76dd6 1812 {
XinZhangMS 0:f7f1f0d76dd6 1813 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1814 LogError("Failure: mqtt_client_subscribe returned error.");
XinZhangMS 0:f7f1f0d76dd6 1815 }
XinZhangMS 0:f7f1f0d76dd6 1816 else
XinZhangMS 0:f7f1f0d76dd6 1817 {
XinZhangMS 0:f7f1f0d76dd6 1818 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_018: [On success IoTHubTransport_MQTT_Common_Subscribe shall return 0.] */
XinZhangMS 0:f7f1f0d76dd6 1819 transport_data->topics_ToSubscribe &= ~topic_subscription;
XinZhangMS 0:f7f1f0d76dd6 1820 transport_data->currPacketState = SUBSCRIBE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1821 }
XinZhangMS 0:f7f1f0d76dd6 1822 }
XinZhangMS 0:f7f1f0d76dd6 1823 else
XinZhangMS 0:f7f1f0d76dd6 1824 {
XinZhangMS 0:f7f1f0d76dd6 1825 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_017: [Upon failure IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 1826 LogError("Failure: subscribe_topic is empty.");
XinZhangMS 0:f7f1f0d76dd6 1827 }
XinZhangMS 0:f7f1f0d76dd6 1828 transport_data->currPacketState = SUBSCRIBE_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1829 }
XinZhangMS 0:f7f1f0d76dd6 1830 else
XinZhangMS 0:f7f1f0d76dd6 1831 {
XinZhangMS 0:f7f1f0d76dd6 1832 transport_data->currPacketState = PUBLISH_TYPE;
XinZhangMS 0:f7f1f0d76dd6 1833 }
XinZhangMS 0:f7f1f0d76dd6 1834 }
XinZhangMS 0:f7f1f0d76dd6 1835
XinZhangMS 0:f7f1f0d76dd6 1836 static const unsigned char* RetrieveMessagePayload(IOTHUB_MESSAGE_HANDLE messageHandle, size_t* length)
XinZhangMS 0:f7f1f0d76dd6 1837 {
XinZhangMS 0:f7f1f0d76dd6 1838 const unsigned char* result;
XinZhangMS 0:f7f1f0d76dd6 1839
XinZhangMS 0:f7f1f0d76dd6 1840 IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1841 if (contentType == IOTHUBMESSAGE_BYTEARRAY)
XinZhangMS 0:f7f1f0d76dd6 1842 {
XinZhangMS 0:f7f1f0d76dd6 1843 if (IoTHubMessage_GetByteArray(messageHandle, &result, length) != IOTHUB_MESSAGE_OK)
XinZhangMS 0:f7f1f0d76dd6 1844 {
XinZhangMS 0:f7f1f0d76dd6 1845 LogError("Failure result from IoTHubMessage_GetByteArray");
XinZhangMS 0:f7f1f0d76dd6 1846 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1847 *length = 0;
XinZhangMS 0:f7f1f0d76dd6 1848 }
XinZhangMS 0:f7f1f0d76dd6 1849 }
XinZhangMS 0:f7f1f0d76dd6 1850 else if (contentType == IOTHUBMESSAGE_STRING)
XinZhangMS 0:f7f1f0d76dd6 1851 {
XinZhangMS 0:f7f1f0d76dd6 1852 result = (const unsigned char*)IoTHubMessage_GetString(messageHandle);
XinZhangMS 0:f7f1f0d76dd6 1853 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 1854 {
XinZhangMS 0:f7f1f0d76dd6 1855 LogError("Failure result from IoTHubMessage_GetString");
XinZhangMS 0:f7f1f0d76dd6 1856 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1857 *length = 0;
XinZhangMS 0:f7f1f0d76dd6 1858 }
XinZhangMS 0:f7f1f0d76dd6 1859 else
XinZhangMS 0:f7f1f0d76dd6 1860 {
XinZhangMS 0:f7f1f0d76dd6 1861 *length = strlen((const char*)result);
XinZhangMS 0:f7f1f0d76dd6 1862 }
XinZhangMS 0:f7f1f0d76dd6 1863 }
XinZhangMS 0:f7f1f0d76dd6 1864 else
XinZhangMS 0:f7f1f0d76dd6 1865 {
XinZhangMS 0:f7f1f0d76dd6 1866 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 1867 *length = 0;
XinZhangMS 0:f7f1f0d76dd6 1868 }
XinZhangMS 0:f7f1f0d76dd6 1869 return result;
XinZhangMS 0:f7f1f0d76dd6 1870 }
XinZhangMS 0:f7f1f0d76dd6 1871
XinZhangMS 0:f7f1f0d76dd6 1872 static int GetTransportProviderIfNecessary(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1873 {
XinZhangMS 0:f7f1f0d76dd6 1874 int result;
XinZhangMS 0:f7f1f0d76dd6 1875
XinZhangMS 0:f7f1f0d76dd6 1876 if (transport_data->xioTransport == NULL)
XinZhangMS 0:f7f1f0d76dd6 1877 {
XinZhangMS 0:f7f1f0d76dd6 1878 // construct address
XinZhangMS 0:f7f1f0d76dd6 1879 const char* hostAddress = STRING_c_str(transport_data->hostAddress);
XinZhangMS 0:f7f1f0d76dd6 1880 MQTT_TRANSPORT_PROXY_OPTIONS mqtt_proxy_options;
XinZhangMS 0:f7f1f0d76dd6 1881
XinZhangMS 0:f7f1f0d76dd6 1882 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_011: [ If no `proxy_data` option has been set, NULL shall be passed as the argument `mqtt_transport_proxy_options` when calling the function `get_io_transport` passed in `IoTHubTransport_MQTT_Common__Create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 1883 mqtt_proxy_options.host_address = transport_data->http_proxy_hostname;
XinZhangMS 0:f7f1f0d76dd6 1884 mqtt_proxy_options.port = transport_data->http_proxy_port;
XinZhangMS 0:f7f1f0d76dd6 1885 mqtt_proxy_options.username = transport_data->http_proxy_username;
XinZhangMS 0:f7f1f0d76dd6 1886 mqtt_proxy_options.password = transport_data->http_proxy_password;
XinZhangMS 0:f7f1f0d76dd6 1887
XinZhangMS 0:f7f1f0d76dd6 1888 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_010: [ If the `proxy_data` option has been set, the proxy options shall be filled in the argument `mqtt_transport_proxy_options` when calling the function `get_io_transport` passed in `IoTHubTransport_MQTT_Common__Create` to obtain the underlying IO handle. ]*/
XinZhangMS 0:f7f1f0d76dd6 1889 transport_data->xioTransport = transport_data->get_io_transport(hostAddress, (transport_data->http_proxy_hostname == NULL) ? NULL : &mqtt_proxy_options);
XinZhangMS 0:f7f1f0d76dd6 1890 if (transport_data->xioTransport == NULL)
XinZhangMS 0:f7f1f0d76dd6 1891 {
XinZhangMS 0:f7f1f0d76dd6 1892 LogError("Unable to create the lower level TLS layer.");
XinZhangMS 0:f7f1f0d76dd6 1893 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1894 }
XinZhangMS 0:f7f1f0d76dd6 1895 else
XinZhangMS 0:f7f1f0d76dd6 1896 {
XinZhangMS 0:f7f1f0d76dd6 1897 transport_data->conn_attempted = true;
XinZhangMS 0:f7f1f0d76dd6 1898 if (transport_data->saved_tls_options != NULL)
XinZhangMS 0:f7f1f0d76dd6 1899 {
XinZhangMS 0:f7f1f0d76dd6 1900 if (OptionHandler_FeedOptions(transport_data->saved_tls_options, transport_data->xioTransport) != OPTIONHANDLER_OK)
XinZhangMS 0:f7f1f0d76dd6 1901 {
XinZhangMS 0:f7f1f0d76dd6 1902 LogError("Failed feeding existing options to new TLS instance.");
XinZhangMS 0:f7f1f0d76dd6 1903 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1904 }
XinZhangMS 0:f7f1f0d76dd6 1905 else
XinZhangMS 0:f7f1f0d76dd6 1906 {
XinZhangMS 0:f7f1f0d76dd6 1907 // The tlsio has the options, so our copy can be deleted
XinZhangMS 0:f7f1f0d76dd6 1908 set_saved_tls_options(transport_data, NULL);
XinZhangMS 0:f7f1f0d76dd6 1909 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1910 }
XinZhangMS 0:f7f1f0d76dd6 1911 }
XinZhangMS 0:f7f1f0d76dd6 1912 else if (IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module) == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
XinZhangMS 0:f7f1f0d76dd6 1913 {
XinZhangMS 0:f7f1f0d76dd6 1914 if (IoTHubClient_Auth_Set_xio_Certificate(transport_data->authorization_module, transport_data->xioTransport) != 0)
XinZhangMS 0:f7f1f0d76dd6 1915 {
XinZhangMS 0:f7f1f0d76dd6 1916 LogError("Unable to create the lower level TLS layer.");
XinZhangMS 0:f7f1f0d76dd6 1917 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1918 }
XinZhangMS 0:f7f1f0d76dd6 1919 else
XinZhangMS 0:f7f1f0d76dd6 1920 {
XinZhangMS 0:f7f1f0d76dd6 1921 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1922 }
XinZhangMS 0:f7f1f0d76dd6 1923 }
XinZhangMS 0:f7f1f0d76dd6 1924 else
XinZhangMS 0:f7f1f0d76dd6 1925 {
XinZhangMS 0:f7f1f0d76dd6 1926 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1927 }
XinZhangMS 0:f7f1f0d76dd6 1928 }
XinZhangMS 0:f7f1f0d76dd6 1929 }
XinZhangMS 0:f7f1f0d76dd6 1930 else
XinZhangMS 0:f7f1f0d76dd6 1931 {
XinZhangMS 0:f7f1f0d76dd6 1932 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1933 }
XinZhangMS 0:f7f1f0d76dd6 1934 return result;
XinZhangMS 0:f7f1f0d76dd6 1935 }
XinZhangMS 0:f7f1f0d76dd6 1936
XinZhangMS 0:f7f1f0d76dd6 1937 //static int is_key_validate(const IOTHUBTRANSPORT_CONFIG* config)
XinZhangMS 0:f7f1f0d76dd6 1938 //{
XinZhangMS 0:f7f1f0d76dd6 1939 // int result;
XinZhangMS 0:f7f1f0d76dd6 1940 // IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(config->auth_module_handle);
XinZhangMS 0:f7f1f0d76dd6 1941 // if (cred_type == IOTHUB_CREDENTIAL_TYPE_X509 || cred_type == IOTHUB_CREDENTIAL_TYPE_X509_ECC)
XinZhangMS 0:f7f1f0d76dd6 1942 // {
XinZhangMS 0:f7f1f0d76dd6 1943 // result = 0;
XinZhangMS 0:f7f1f0d76dd6 1944 // }
XinZhangMS 0:f7f1f0d76dd6 1945 // else
XinZhangMS 0:f7f1f0d76dd6 1946 // {
XinZhangMS 0:f7f1f0d76dd6 1947 // if (config->upperConfig->deviceKey == NULL && config->upperConfig->deviceSasToken == NULL)
XinZhangMS 0:f7f1f0d76dd6 1948 // {
XinZhangMS 0:f7f1f0d76dd6 1949 // if (IoTHubClient_Auth_Get_DeviceKey(config->auth_module_handle) == NULL)
XinZhangMS 0:f7f1f0d76dd6 1950 // {
XinZhangMS 0:f7f1f0d76dd6 1951 // result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1952 // }
XinZhangMS 0:f7f1f0d76dd6 1953 // else
XinZhangMS 0:f7f1f0d76dd6 1954 // {
XinZhangMS 0:f7f1f0d76dd6 1955 // result = 0;
XinZhangMS 0:f7f1f0d76dd6 1956 // }
XinZhangMS 0:f7f1f0d76dd6 1957 // }
XinZhangMS 0:f7f1f0d76dd6 1958 // else
XinZhangMS 0:f7f1f0d76dd6 1959 // {
XinZhangMS 0:f7f1f0d76dd6 1960 // result = 0;
XinZhangMS 0:f7f1f0d76dd6 1961 // }
XinZhangMS 0:f7f1f0d76dd6 1962 // }
XinZhangMS 0:f7f1f0d76dd6 1963 // return result;
XinZhangMS 0:f7f1f0d76dd6 1964 //}
XinZhangMS 0:f7f1f0d76dd6 1965
XinZhangMS 0:f7f1f0d76dd6 1966 static STRING_HANDLE buildClientId(const char* device_id, const char* module_id)
XinZhangMS 0:f7f1f0d76dd6 1967 {
XinZhangMS 0:f7f1f0d76dd6 1968 if (module_id == NULL)
XinZhangMS 0:f7f1f0d76dd6 1969 {
XinZhangMS 0:f7f1f0d76dd6 1970 return STRING_construct_sprintf("%s", device_id);
XinZhangMS 0:f7f1f0d76dd6 1971 }
XinZhangMS 0:f7f1f0d76dd6 1972 else
XinZhangMS 0:f7f1f0d76dd6 1973 {
XinZhangMS 0:f7f1f0d76dd6 1974 return STRING_construct_sprintf("%s/%s", device_id, module_id);
XinZhangMS 0:f7f1f0d76dd6 1975 }
XinZhangMS 0:f7f1f0d76dd6 1976 }
XinZhangMS 0:f7f1f0d76dd6 1977
XinZhangMS 0:f7f1f0d76dd6 1978 static int SendMqttConnectMsg(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 1979 {
XinZhangMS 0:f7f1f0d76dd6 1980 int result;
XinZhangMS 0:f7f1f0d76dd6 1981
XinZhangMS 0:f7f1f0d76dd6 1982 char* sasToken = NULL;
XinZhangMS 0:f7f1f0d76dd6 1983 result = 0;
XinZhangMS 0:f7f1f0d76dd6 1984
XinZhangMS 0:f7f1f0d76dd6 1985 IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module);
XinZhangMS 0:f7f1f0d76dd6 1986 if (cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY || cred_type == IOTHUB_CREDENTIAL_TYPE_DEVICE_AUTH)
XinZhangMS 0:f7f1f0d76dd6 1987 {
XinZhangMS 0:f7f1f0d76dd6 1988 sasToken = IoTHubClient_Auth_Get_SasToken(transport_data->authorization_module, STRING_c_str(transport_data->devicesAndModulesPath), transport_data->option_sas_token_lifetime_secs, NULL);
XinZhangMS 0:f7f1f0d76dd6 1989 if (sasToken == NULL)
XinZhangMS 0:f7f1f0d76dd6 1990 {
XinZhangMS 0:f7f1f0d76dd6 1991 LogError("failure getting sas token from IoTHubClient_Auth_Get_SasToken.");
XinZhangMS 0:f7f1f0d76dd6 1992 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 1993 }
XinZhangMS 0:f7f1f0d76dd6 1994 }
XinZhangMS 0:f7f1f0d76dd6 1995 else if (cred_type == IOTHUB_CREDENTIAL_TYPE_SAS_TOKEN)
XinZhangMS 0:f7f1f0d76dd6 1996 {
XinZhangMS 0:f7f1f0d76dd6 1997 SAS_TOKEN_STATUS token_status = IoTHubClient_Auth_Is_SasToken_Valid(transport_data->authorization_module);
XinZhangMS 0:f7f1f0d76dd6 1998 if (token_status == SAS_TOKEN_STATUS_INVALID)
XinZhangMS 0:f7f1f0d76dd6 1999 {
XinZhangMS 0:f7f1f0d76dd6 2000 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN);
XinZhangMS 0:f7f1f0d76dd6 2001 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2002 }
XinZhangMS 0:f7f1f0d76dd6 2003 else if (token_status == SAS_TOKEN_STATUS_FAILED)
XinZhangMS 0:f7f1f0d76dd6 2004 {
XinZhangMS 0:f7f1f0d76dd6 2005 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL);
XinZhangMS 0:f7f1f0d76dd6 2006 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2007 }
XinZhangMS 0:f7f1f0d76dd6 2008 else
XinZhangMS 0:f7f1f0d76dd6 2009 {
XinZhangMS 0:f7f1f0d76dd6 2010 sasToken = IoTHubClient_Auth_Get_SasToken(transport_data->authorization_module, NULL, 0, NULL);
XinZhangMS 0:f7f1f0d76dd6 2011 if (sasToken == NULL)
XinZhangMS 0:f7f1f0d76dd6 2012 {
XinZhangMS 0:f7f1f0d76dd6 2013 LogError("failure getting sas Token.");
XinZhangMS 0:f7f1f0d76dd6 2014 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2015 }
XinZhangMS 0:f7f1f0d76dd6 2016 }
XinZhangMS 0:f7f1f0d76dd6 2017 }
XinZhangMS 0:f7f1f0d76dd6 2018
XinZhangMS 0:f7f1f0d76dd6 2019 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 2020 {
XinZhangMS 0:f7f1f0d76dd6 2021 if (!transport_data->isProductInfoSet)
XinZhangMS 0:f7f1f0d76dd6 2022 {
XinZhangMS 0:f7f1f0d76dd6 2023 // This requires the iothubClientHandle, which sadly the MQTT transport only gets on DoWork, so this code still needs to remain here.
XinZhangMS 0:f7f1f0d76dd6 2024 // The correct place for this would be in the Create method, but we don't get the client handle there.
XinZhangMS 0:f7f1f0d76dd6 2025 // Also, when device multiplexing is used, the customer creates the transport directly and explicitly, when the client is still not created.
XinZhangMS 0:f7f1f0d76dd6 2026 // This will be a major hurdle when we add device multiplexing to MQTT transport.
XinZhangMS 0:f7f1f0d76dd6 2027
XinZhangMS 0:f7f1f0d76dd6 2028 void* product_info;
XinZhangMS 0:f7f1f0d76dd6 2029 STRING_HANDLE clone;
XinZhangMS 0:f7f1f0d76dd6 2030 if ((IoTHubClientCore_LL_GetOption(transport_data->llClientHandle, OPTION_PRODUCT_INFO, &product_info) == IOTHUB_CLIENT_ERROR) || (product_info == NULL))
XinZhangMS 0:f7f1f0d76dd6 2031 {
XinZhangMS 0:f7f1f0d76dd6 2032 clone = STRING_construct_sprintf("%s%%2F%s", CLIENT_DEVICE_TYPE_PREFIX, IOTHUB_SDK_VERSION);
XinZhangMS 0:f7f1f0d76dd6 2033 }
XinZhangMS 0:f7f1f0d76dd6 2034 else
XinZhangMS 0:f7f1f0d76dd6 2035 {
XinZhangMS 0:f7f1f0d76dd6 2036 clone = URL_Encode(product_info);
XinZhangMS 0:f7f1f0d76dd6 2037 }
XinZhangMS 0:f7f1f0d76dd6 2038
XinZhangMS 0:f7f1f0d76dd6 2039 if (clone == NULL)
XinZhangMS 0:f7f1f0d76dd6 2040 {
XinZhangMS 0:f7f1f0d76dd6 2041 LogError("Failed obtaining the product info");
XinZhangMS 0:f7f1f0d76dd6 2042 }
XinZhangMS 0:f7f1f0d76dd6 2043 else
XinZhangMS 0:f7f1f0d76dd6 2044 {
XinZhangMS 0:f7f1f0d76dd6 2045 if (STRING_concat_with_STRING(transport_data->configPassedThroughUsername, clone) != 0)
XinZhangMS 0:f7f1f0d76dd6 2046 {
XinZhangMS 0:f7f1f0d76dd6 2047 LogError("Failed concatenating the product info");
XinZhangMS 0:f7f1f0d76dd6 2048 }
XinZhangMS 0:f7f1f0d76dd6 2049 else
XinZhangMS 0:f7f1f0d76dd6 2050 {
XinZhangMS 0:f7f1f0d76dd6 2051 transport_data->isProductInfoSet = true;
XinZhangMS 0:f7f1f0d76dd6 2052 }
XinZhangMS 0:f7f1f0d76dd6 2053
XinZhangMS 0:f7f1f0d76dd6 2054 STRING_delete(clone);
XinZhangMS 0:f7f1f0d76dd6 2055 }
XinZhangMS 0:f7f1f0d76dd6 2056 }
XinZhangMS 0:f7f1f0d76dd6 2057
XinZhangMS 0:f7f1f0d76dd6 2058 STRING_HANDLE clientId;
XinZhangMS 0:f7f1f0d76dd6 2059
XinZhangMS 0:f7f1f0d76dd6 2060 clientId = buildClientId(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id));
XinZhangMS 0:f7f1f0d76dd6 2061 if (NULL == clientId)
XinZhangMS 0:f7f1f0d76dd6 2062 {
XinZhangMS 0:f7f1f0d76dd6 2063 LogError("Unable to allocate clientId");
XinZhangMS 0:f7f1f0d76dd6 2064 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2065 }
XinZhangMS 0:f7f1f0d76dd6 2066 else
XinZhangMS 0:f7f1f0d76dd6 2067 {
XinZhangMS 0:f7f1f0d76dd6 2068 MQTT_CLIENT_OPTIONS options = { 0 };
XinZhangMS 0:f7f1f0d76dd6 2069 options.clientId = (char*)STRING_c_str(clientId);
XinZhangMS 0:f7f1f0d76dd6 2070 options.willMessage = NULL;
XinZhangMS 0:f7f1f0d76dd6 2071 options.username = (char*)STRING_c_str(transport_data->configPassedThroughUsername);
XinZhangMS 0:f7f1f0d76dd6 2072 if (sasToken != NULL)
XinZhangMS 0:f7f1f0d76dd6 2073 {
XinZhangMS 0:f7f1f0d76dd6 2074 options.password = sasToken;
XinZhangMS 0:f7f1f0d76dd6 2075 }
XinZhangMS 0:f7f1f0d76dd6 2076 options.keepAliveInterval = transport_data->keepAliveValue;
XinZhangMS 0:f7f1f0d76dd6 2077 options.useCleanSession = false;
XinZhangMS 0:f7f1f0d76dd6 2078 options.qualityOfServiceValue = DELIVER_AT_LEAST_ONCE;
XinZhangMS 0:f7f1f0d76dd6 2079
XinZhangMS 0:f7f1f0d76dd6 2080 if (GetTransportProviderIfNecessary(transport_data) == 0)
XinZhangMS 0:f7f1f0d76dd6 2081 {
XinZhangMS 0:f7f1f0d76dd6 2082 if (mqtt_client_connect(transport_data->mqttClient, transport_data->xioTransport, &options) != 0)
XinZhangMS 0:f7f1f0d76dd6 2083 {
XinZhangMS 0:f7f1f0d76dd6 2084 LogError("failure connecting to address %s.", STRING_c_str(transport_data->hostAddress));
XinZhangMS 0:f7f1f0d76dd6 2085 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2086 }
XinZhangMS 0:f7f1f0d76dd6 2087 else
XinZhangMS 0:f7f1f0d76dd6 2088 {
XinZhangMS 0:f7f1f0d76dd6 2089 (void)tickcounter_get_current_ms(transport_data->msgTickCounter, &transport_data->mqtt_connect_time);
XinZhangMS 0:f7f1f0d76dd6 2090 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2091 }
XinZhangMS 0:f7f1f0d76dd6 2092 }
XinZhangMS 0:f7f1f0d76dd6 2093 else
XinZhangMS 0:f7f1f0d76dd6 2094 {
XinZhangMS 0:f7f1f0d76dd6 2095 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2096 }
XinZhangMS 0:f7f1f0d76dd6 2097
XinZhangMS 0:f7f1f0d76dd6 2098 if (sasToken != NULL)
XinZhangMS 0:f7f1f0d76dd6 2099 {
XinZhangMS 0:f7f1f0d76dd6 2100 free(sasToken);
XinZhangMS 0:f7f1f0d76dd6 2101 }
XinZhangMS 0:f7f1f0d76dd6 2102 STRING_delete(clientId);
XinZhangMS 0:f7f1f0d76dd6 2103 }
XinZhangMS 0:f7f1f0d76dd6 2104
XinZhangMS 0:f7f1f0d76dd6 2105 }
XinZhangMS 0:f7f1f0d76dd6 2106 return result;
XinZhangMS 0:f7f1f0d76dd6 2107 }
XinZhangMS 0:f7f1f0d76dd6 2108
XinZhangMS 0:f7f1f0d76dd6 2109 static int InitializeConnection(PMQTTTRANSPORT_HANDLE_DATA transport_data)
XinZhangMS 0:f7f1f0d76dd6 2110 {
XinZhangMS 0:f7f1f0d76dd6 2111 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 2112
XinZhangMS 0:f7f1f0d76dd6 2113 // Make sure we're not destroying the object
XinZhangMS 0:f7f1f0d76dd6 2114 if (!transport_data->isDestroyCalled)
XinZhangMS 0:f7f1f0d76dd6 2115 {
XinZhangMS 0:f7f1f0d76dd6 2116 RETRY_ACTION retry_action = RETRY_ACTION_RETRY_LATER;
XinZhangMS 0:f7f1f0d76dd6 2117
XinZhangMS 0:f7f1f0d76dd6 2118 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_007: [ IoTHubTransport_MQTT_Common_DoWork shall try to reconnect according to the current retry policy set ]
XinZhangMS 0:f7f1f0d76dd6 2119 if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_NOT_CONNECTED && transport_data->isRecoverableError &&
XinZhangMS 0:f7f1f0d76dd6 2120 (retry_control_should_retry(transport_data->retry_control_handle, &retry_action) != 0 || retry_action == RETRY_ACTION_RETRY_NOW))
XinZhangMS 0:f7f1f0d76dd6 2121 {
XinZhangMS 0:f7f1f0d76dd6 2122 // Note: in case retry_control_should_retry fails, the reconnection shall be attempted anyway (defaulting to policy IOTHUB_CLIENT_RETRY_IMMEDIATE).
XinZhangMS 0:f7f1f0d76dd6 2123
XinZhangMS 0:f7f1f0d76dd6 2124 if (tickcounter_get_current_ms(transport_data->msgTickCounter, &transport_data->connectTick) != 0)
XinZhangMS 0:f7f1f0d76dd6 2125 {
XinZhangMS 0:f7f1f0d76dd6 2126 transport_data->connectFailCount++;
XinZhangMS 0:f7f1f0d76dd6 2127 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2128 }
XinZhangMS 0:f7f1f0d76dd6 2129 else
XinZhangMS 0:f7f1f0d76dd6 2130 {
XinZhangMS 0:f7f1f0d76dd6 2131 ResetConnectionIfNecessary(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2132
XinZhangMS 0:f7f1f0d76dd6 2133 if (SendMqttConnectMsg(transport_data) != 0)
XinZhangMS 0:f7f1f0d76dd6 2134 {
XinZhangMS 0:f7f1f0d76dd6 2135 transport_data->connectFailCount++;
XinZhangMS 0:f7f1f0d76dd6 2136 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2137 }
XinZhangMS 0:f7f1f0d76dd6 2138 else
XinZhangMS 0:f7f1f0d76dd6 2139 {
XinZhangMS 0:f7f1f0d76dd6 2140 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_CONNECTING;
XinZhangMS 0:f7f1f0d76dd6 2141 transport_data->connectFailCount = 0;
XinZhangMS 0:f7f1f0d76dd6 2142 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2143 }
XinZhangMS 0:f7f1f0d76dd6 2144 }
XinZhangMS 0:f7f1f0d76dd6 2145 }
XinZhangMS 0:f7f1f0d76dd6 2146 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_001: [ IoTHubTransport_MQTT_Common_DoWork shall trigger reconnection if the mqtt_client_connect does not complete within `keepalive` seconds]
XinZhangMS 0:f7f1f0d76dd6 2147 else if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_CONNECTING)
XinZhangMS 0:f7f1f0d76dd6 2148 {
XinZhangMS 0:f7f1f0d76dd6 2149 tickcounter_ms_t current_time;
XinZhangMS 0:f7f1f0d76dd6 2150 if (tickcounter_get_current_ms(transport_data->msgTickCounter, &current_time) != 0)
XinZhangMS 0:f7f1f0d76dd6 2151 {
XinZhangMS 0:f7f1f0d76dd6 2152 LogError("failed verifying MQTT_CLIENT_STATUS_CONNECTING timeout");
XinZhangMS 0:f7f1f0d76dd6 2153 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2154 }
XinZhangMS 0:f7f1f0d76dd6 2155 else if ((current_time - transport_data->mqtt_connect_time) / 1000 > transport_data->connect_timeout_in_sec)
XinZhangMS 0:f7f1f0d76dd6 2156 {
XinZhangMS 0:f7f1f0d76dd6 2157 LogError("mqtt_client timed out waiting for CONNACK");
XinZhangMS 0:f7f1f0d76dd6 2158 DisconnectFromClient(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2159 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2160 }
XinZhangMS 0:f7f1f0d76dd6 2161 }
XinZhangMS 0:f7f1f0d76dd6 2162 else if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_CONNECTED)
XinZhangMS 0:f7f1f0d76dd6 2163 {
XinZhangMS 0:f7f1f0d76dd6 2164 // We are connected and not being closed, so does SAS need to reconnect?
XinZhangMS 0:f7f1f0d76dd6 2165 tickcounter_ms_t current_time;
XinZhangMS 0:f7f1f0d76dd6 2166 if (tickcounter_get_current_ms(transport_data->msgTickCounter, &current_time) != 0)
XinZhangMS 0:f7f1f0d76dd6 2167 {
XinZhangMS 0:f7f1f0d76dd6 2168 transport_data->connectFailCount++;
XinZhangMS 0:f7f1f0d76dd6 2169 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2170 }
XinZhangMS 0:f7f1f0d76dd6 2171 else
XinZhangMS 0:f7f1f0d76dd6 2172 {
XinZhangMS 0:f7f1f0d76dd6 2173 if ((current_time - transport_data->mqtt_connect_time) / 1000 > (transport_data->option_sas_token_lifetime_secs*SAS_REFRESH_MULTIPLIER))
XinZhangMS 0:f7f1f0d76dd6 2174 {
XinZhangMS 0:f7f1f0d76dd6 2175 /* 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. ] */
XinZhangMS 0:f7f1f0d76dd6 2176 OPTIONHANDLER_HANDLE options = xio_retrieveoptions(transport_data->xioTransport);
XinZhangMS 0:f7f1f0d76dd6 2177 set_saved_tls_options(transport_data, options);
XinZhangMS 0:f7f1f0d76dd6 2178 (void)mqtt_client_disconnect(transport_data->mqttClient, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 2179 xio_destroy(transport_data->xioTransport);
XinZhangMS 0:f7f1f0d76dd6 2180 transport_data->xioTransport = NULL;
XinZhangMS 0:f7f1f0d76dd6 2181
XinZhangMS 0:f7f1f0d76dd6 2182 IoTHubClientCore_LL_ConnectionStatusCallBack(transport_data->llClientHandle, IOTHUB_CLIENT_CONNECTION_UNAUTHENTICATED, IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN);
XinZhangMS 0:f7f1f0d76dd6 2183 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 2184 transport_data->currPacketState = UNKNOWN_TYPE;
XinZhangMS 0:f7f1f0d76dd6 2185 transport_data->device_twin_get_sent = false;
XinZhangMS 0:f7f1f0d76dd6 2186 if (transport_data->topic_MqttMessage != NULL)
XinZhangMS 0:f7f1f0d76dd6 2187 {
XinZhangMS 0:f7f1f0d76dd6 2188 transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2189 }
XinZhangMS 0:f7f1f0d76dd6 2190 if (transport_data->topic_GetState != NULL)
XinZhangMS 0:f7f1f0d76dd6 2191 {
XinZhangMS 0:f7f1f0d76dd6 2192 transport_data->topics_ToSubscribe |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2193 }
XinZhangMS 0:f7f1f0d76dd6 2194 if (transport_data->topic_NotifyState != NULL)
XinZhangMS 0:f7f1f0d76dd6 2195 {
XinZhangMS 0:f7f1f0d76dd6 2196 transport_data->topics_ToSubscribe |= SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2197 }
XinZhangMS 0:f7f1f0d76dd6 2198 if (transport_data->topic_DeviceMethods != NULL)
XinZhangMS 0:f7f1f0d76dd6 2199 {
XinZhangMS 0:f7f1f0d76dd6 2200 transport_data->topics_ToSubscribe |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2201 }
XinZhangMS 0:f7f1f0d76dd6 2202 if (transport_data->topic_InputQueue != NULL)
XinZhangMS 0:f7f1f0d76dd6 2203 {
XinZhangMS 0:f7f1f0d76dd6 2204 transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2205 }
XinZhangMS 0:f7f1f0d76dd6 2206 }
XinZhangMS 0:f7f1f0d76dd6 2207 }
XinZhangMS 0:f7f1f0d76dd6 2208 }
XinZhangMS 0:f7f1f0d76dd6 2209 }
XinZhangMS 0:f7f1f0d76dd6 2210 return result;
XinZhangMS 0:f7f1f0d76dd6 2211 }
XinZhangMS 0:f7f1f0d76dd6 2212
XinZhangMS 0:f7f1f0d76dd6 2213 static STRING_HANDLE buildConfigForUsername(const IOTHUB_CLIENT_CONFIG* upperConfig, const char* moduleId)
XinZhangMS 0:f7f1f0d76dd6 2214 {
XinZhangMS 0:f7f1f0d76dd6 2215 if (moduleId == NULL)
XinZhangMS 0:f7f1f0d76dd6 2216 {
XinZhangMS 0:f7f1f0d76dd6 2217 return STRING_construct_sprintf("%s.%s/%s/?api-version=%s&DeviceClientType=", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId, IOTHUB_API_VERSION);
XinZhangMS 0:f7f1f0d76dd6 2218 }
XinZhangMS 0:f7f1f0d76dd6 2219 else
XinZhangMS 0:f7f1f0d76dd6 2220 {
XinZhangMS 0:f7f1f0d76dd6 2221 return STRING_construct_sprintf("%s.%s/%s/%s/?api-version=%s&DeviceClientType=", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId, moduleId, IOTHUB_API_VERSION);
XinZhangMS 0:f7f1f0d76dd6 2222 }
XinZhangMS 0:f7f1f0d76dd6 2223 }
XinZhangMS 0:f7f1f0d76dd6 2224
XinZhangMS 0:f7f1f0d76dd6 2225 static STRING_HANDLE buildMqttEventString(const char* device_id, const char* module_id)
XinZhangMS 0:f7f1f0d76dd6 2226 {
XinZhangMS 0:f7f1f0d76dd6 2227 if (module_id == NULL)
XinZhangMS 0:f7f1f0d76dd6 2228 {
XinZhangMS 0:f7f1f0d76dd6 2229 return STRING_construct_sprintf(TOPIC_DEVICE_DEVICE, device_id);
XinZhangMS 0:f7f1f0d76dd6 2230 }
XinZhangMS 0:f7f1f0d76dd6 2231 else
XinZhangMS 0:f7f1f0d76dd6 2232 {
XinZhangMS 0:f7f1f0d76dd6 2233 return STRING_construct_sprintf(TOPIC_DEVICE_DEVICE_MODULE, device_id, module_id);
XinZhangMS 0:f7f1f0d76dd6 2234 }
XinZhangMS 0:f7f1f0d76dd6 2235 }
XinZhangMS 0:f7f1f0d76dd6 2236
XinZhangMS 0:f7f1f0d76dd6 2237 static STRING_HANDLE buildDevicesAndModulesPath(const IOTHUB_CLIENT_CONFIG* upperConfig, const char* moduleId)
XinZhangMS 0:f7f1f0d76dd6 2238 {
XinZhangMS 0:f7f1f0d76dd6 2239 if (moduleId == NULL)
XinZhangMS 0:f7f1f0d76dd6 2240 {
XinZhangMS 0:f7f1f0d76dd6 2241 return STRING_construct_sprintf("%s.%s/devices/%s", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId);
XinZhangMS 0:f7f1f0d76dd6 2242 }
XinZhangMS 0:f7f1f0d76dd6 2243 else
XinZhangMS 0:f7f1f0d76dd6 2244 {
XinZhangMS 0:f7f1f0d76dd6 2245 return STRING_construct_sprintf("%s.%s/devices/%s/modules/%s", upperConfig->iotHubName, upperConfig->iotHubSuffix, upperConfig->deviceId, moduleId);
XinZhangMS 0:f7f1f0d76dd6 2246 }
XinZhangMS 0:f7f1f0d76dd6 2247 }
XinZhangMS 0:f7f1f0d76dd6 2248
XinZhangMS 0:f7f1f0d76dd6 2249 static PMQTTTRANSPORT_HANDLE_DATA InitializeTransportHandleData(const IOTHUB_CLIENT_CONFIG* upperConfig, PDLIST_ENTRY waitingToSend, IOTHUB_AUTHORIZATION_HANDLE auth_module, const char* moduleId)
XinZhangMS 0:f7f1f0d76dd6 2250 {
XinZhangMS 0:f7f1f0d76dd6 2251 PMQTTTRANSPORT_HANDLE_DATA state = (PMQTTTRANSPORT_HANDLE_DATA)malloc(sizeof(MQTTTRANSPORT_HANDLE_DATA));
XinZhangMS 0:f7f1f0d76dd6 2252 if (state == NULL)
XinZhangMS 0:f7f1f0d76dd6 2253 {
XinZhangMS 0:f7f1f0d76dd6 2254 LogError("Could not create MQTT transport state. Memory allocation failed.");
XinZhangMS 0:f7f1f0d76dd6 2255 }
XinZhangMS 0:f7f1f0d76dd6 2256 else
XinZhangMS 0:f7f1f0d76dd6 2257 {
XinZhangMS 0:f7f1f0d76dd6 2258 memset(state, 0, sizeof(MQTTTRANSPORT_HANDLE_DATA));
XinZhangMS 0:f7f1f0d76dd6 2259 if ((state->msgTickCounter = tickcounter_create()) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2260 {
XinZhangMS 0:f7f1f0d76dd6 2261 LogError("Invalid Argument: iotHubName is empty");
XinZhangMS 0:f7f1f0d76dd6 2262 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2263 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2264 }
XinZhangMS 0:f7f1f0d76dd6 2265 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_09_005: [ MQTT transport shall use EXPONENTIAL_WITH_BACK_OFF as default retry policy ]
XinZhangMS 0:f7f1f0d76dd6 2266 else if ((state->retry_control_handle = retry_control_create(DEFAULT_RETRY_POLICY, DEFAULT_RETRY_TIMEOUT_IN_SECONDS)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2267 {
XinZhangMS 0:f7f1f0d76dd6 2268 LogError("Failed creating default retry control");
XinZhangMS 0:f7f1f0d76dd6 2269 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2270 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2271 }
XinZhangMS 0:f7f1f0d76dd6 2272 else if ((state->device_id = STRING_construct(upperConfig->deviceId)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2273 {
XinZhangMS 0:f7f1f0d76dd6 2274 LogError("failure constructing device_id.");
XinZhangMS 0:f7f1f0d76dd6 2275 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2276 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2277 }
XinZhangMS 0:f7f1f0d76dd6 2278 else if ((moduleId != NULL) && ((state->module_id = STRING_construct(moduleId)) == NULL))
XinZhangMS 0:f7f1f0d76dd6 2279 {
XinZhangMS 0:f7f1f0d76dd6 2280 LogError("failure constructing module_id.");
XinZhangMS 0:f7f1f0d76dd6 2281 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2282 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2283 }
XinZhangMS 0:f7f1f0d76dd6 2284 else if ((state->devicesAndModulesPath = buildDevicesAndModulesPath(upperConfig, moduleId)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2285 {
XinZhangMS 0:f7f1f0d76dd6 2286 LogError("failure constructing devicesPath.");
XinZhangMS 0:f7f1f0d76dd6 2287 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2288 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2289 }
XinZhangMS 0:f7f1f0d76dd6 2290 else
XinZhangMS 0:f7f1f0d76dd6 2291 {
XinZhangMS 0:f7f1f0d76dd6 2292 if ((state->topic_MqttEvent = buildMqttEventString(upperConfig->deviceId, moduleId)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2293 {
XinZhangMS 0:f7f1f0d76dd6 2294 LogError("Could not create topic_MqttEvent for MQTT");
XinZhangMS 0:f7f1f0d76dd6 2295 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2296 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2297 }
XinZhangMS 0:f7f1f0d76dd6 2298 else
XinZhangMS 0:f7f1f0d76dd6 2299 {
XinZhangMS 0:f7f1f0d76dd6 2300 state->mqttClient = mqtt_client_init(mqtt_notification_callback, mqtt_operation_complete_callback, state, mqtt_error_callback, state);
XinZhangMS 0:f7f1f0d76dd6 2301 if (state->mqttClient == NULL)
XinZhangMS 0:f7f1f0d76dd6 2302 {
XinZhangMS 0:f7f1f0d76dd6 2303 LogError("failure initializing mqtt client.");
XinZhangMS 0:f7f1f0d76dd6 2304 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2305 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2306 }
XinZhangMS 0:f7f1f0d76dd6 2307 else
XinZhangMS 0:f7f1f0d76dd6 2308 {
XinZhangMS 0:f7f1f0d76dd6 2309 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2310 if (upperConfig->protocolGatewayHostName == NULL)
XinZhangMS 0:f7f1f0d76dd6 2311 {
XinZhangMS 0:f7f1f0d76dd6 2312 state->hostAddress = STRING_construct_sprintf("%s.%s", upperConfig->iotHubName, upperConfig->iotHubSuffix);
XinZhangMS 0:f7f1f0d76dd6 2313 }
XinZhangMS 0:f7f1f0d76dd6 2314 else
XinZhangMS 0:f7f1f0d76dd6 2315 {
XinZhangMS 0:f7f1f0d76dd6 2316 state->hostAddress = STRING_construct(upperConfig->protocolGatewayHostName);
XinZhangMS 0:f7f1f0d76dd6 2317 }
XinZhangMS 0:f7f1f0d76dd6 2318
XinZhangMS 0:f7f1f0d76dd6 2319 if (state->hostAddress == NULL)
XinZhangMS 0:f7f1f0d76dd6 2320 {
XinZhangMS 0:f7f1f0d76dd6 2321 LogError("failure constructing host address.");
XinZhangMS 0:f7f1f0d76dd6 2322 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2323 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2324 }
XinZhangMS 0:f7f1f0d76dd6 2325 else if ((state->configPassedThroughUsername = buildConfigForUsername(upperConfig, moduleId)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 2326 {
XinZhangMS 0:f7f1f0d76dd6 2327 free_transport_handle_data(state);
XinZhangMS 0:f7f1f0d76dd6 2328 state = NULL;
XinZhangMS 0:f7f1f0d76dd6 2329 }
XinZhangMS 0:f7f1f0d76dd6 2330 else
XinZhangMS 0:f7f1f0d76dd6 2331 {
XinZhangMS 0:f7f1f0d76dd6 2332 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_010: [IoTHubTransport_MQTT_Common_Create shall allocate memory to save its internal state where all topics, hostname, device_id, device_key, sasTokenSr and client handle shall be saved.] */
XinZhangMS 0:f7f1f0d76dd6 2333 DList_InitializeListHead(&(state->telemetry_waitingForAck));
XinZhangMS 0:f7f1f0d76dd6 2334 DList_InitializeListHead(&(state->ack_waiting_queue));
XinZhangMS 0:f7f1f0d76dd6 2335 state->isDestroyCalled = false;
XinZhangMS 0:f7f1f0d76dd6 2336 state->isRegistered = false;
XinZhangMS 0:f7f1f0d76dd6 2337 state->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 2338 state->device_twin_get_sent = false;
XinZhangMS 0:f7f1f0d76dd6 2339 state->isRecoverableError = true;
XinZhangMS 0:f7f1f0d76dd6 2340 state->packetId = 1;
XinZhangMS 0:f7f1f0d76dd6 2341 state->llClientHandle = NULL;
XinZhangMS 0:f7f1f0d76dd6 2342 state->xioTransport = NULL;
XinZhangMS 0:f7f1f0d76dd6 2343 state->portNum = 0;
XinZhangMS 0:f7f1f0d76dd6 2344 state->waitingToSend = waitingToSend;
XinZhangMS 0:f7f1f0d76dd6 2345 state->currPacketState = CONNECT_TYPE;
XinZhangMS 0:f7f1f0d76dd6 2346 state->keepAliveValue = DEFAULT_MQTT_KEEPALIVE;
XinZhangMS 0:f7f1f0d76dd6 2347 state->connect_timeout_in_sec = DEFAULT_CONNACK_TIMEOUT;
XinZhangMS 0:f7f1f0d76dd6 2348 state->connectFailCount = 0;
XinZhangMS 0:f7f1f0d76dd6 2349 state->connectTick = 0;
XinZhangMS 0:f7f1f0d76dd6 2350 state->topic_MqttMessage = NULL;
XinZhangMS 0:f7f1f0d76dd6 2351 state->topic_GetState = NULL;
XinZhangMS 0:f7f1f0d76dd6 2352 state->topic_NotifyState = NULL;
XinZhangMS 0:f7f1f0d76dd6 2353 state->topics_ToSubscribe = UNSUBSCRIBE_FROM_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2354 state->topic_DeviceMethods = NULL;
XinZhangMS 0:f7f1f0d76dd6 2355 state->topic_InputQueue = NULL;
XinZhangMS 0:f7f1f0d76dd6 2356 state->log_trace = state->raw_trace = false;
XinZhangMS 0:f7f1f0d76dd6 2357 srand((unsigned int)get_time(NULL));
XinZhangMS 0:f7f1f0d76dd6 2358 state->authorization_module = auth_module;
XinZhangMS 0:f7f1f0d76dd6 2359 state->isProductInfoSet = false;
XinZhangMS 0:f7f1f0d76dd6 2360 state->option_sas_token_lifetime_secs = SAS_TOKEN_DEFAULT_LIFETIME;
XinZhangMS 0:f7f1f0d76dd6 2361 state->auto_url_encode_decode = false;
XinZhangMS 0:f7f1f0d76dd6 2362 state->conn_attempted = false;
XinZhangMS 0:f7f1f0d76dd6 2363 }
XinZhangMS 0:f7f1f0d76dd6 2364 }
XinZhangMS 0:f7f1f0d76dd6 2365 }
XinZhangMS 0:f7f1f0d76dd6 2366 }
XinZhangMS 0:f7f1f0d76dd6 2367 }
XinZhangMS 0:f7f1f0d76dd6 2368 return state;
XinZhangMS 0:f7f1f0d76dd6 2369 }
XinZhangMS 0:f7f1f0d76dd6 2370
XinZhangMS 0:f7f1f0d76dd6 2371 TRANSPORT_LL_HANDLE IoTHubTransport_MQTT_Common_Create(const IOTHUBTRANSPORT_CONFIG* config, MQTT_GET_IO_TRANSPORT get_io_transport)
XinZhangMS 0:f7f1f0d76dd6 2372 {
XinZhangMS 0:f7f1f0d76dd6 2373 PMQTTTRANSPORT_HANDLE_DATA result;
XinZhangMS 0:f7f1f0d76dd6 2374 size_t deviceIdSize;
XinZhangMS 0:f7f1f0d76dd6 2375
XinZhangMS 0:f7f1f0d76dd6 2376 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_001: [If parameter config is NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2377 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_041: [ if get_io_transport is NULL then IoTHubTransport_MQTT_Common_Create shall return NULL. ] */
XinZhangMS 0:f7f1f0d76dd6 2378 if (config == NULL || get_io_transport == NULL)
XinZhangMS 0:f7f1f0d76dd6 2379 {
XinZhangMS 0:f7f1f0d76dd6 2380 LogError("Invalid Argument: Config Parameter is NULL.");
XinZhangMS 0:f7f1f0d76dd6 2381 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2382 }
XinZhangMS 0:f7f1f0d76dd6 2383 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig, auth_module_handle or waitingToSend are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2384 else if (config->auth_module_handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 2385 {
XinZhangMS 0:f7f1f0d76dd6 2386 LogError("Invalid Argument: auth_module_handle is NULL)");
XinZhangMS 0:f7f1f0d76dd6 2387 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2388 }
XinZhangMS 0:f7f1f0d76dd6 2389 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig or waitingToSend are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2390 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2391 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_003: [If both deviceKey & deviceSasToken fields are NOT NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2392 else if (config->upperConfig == NULL ||
XinZhangMS 0:f7f1f0d76dd6 2393 config->upperConfig->protocol == NULL ||
XinZhangMS 0:f7f1f0d76dd6 2394 config->upperConfig->deviceId == NULL ||
XinZhangMS 0:f7f1f0d76dd6 2395 ((config->upperConfig->deviceKey != NULL) && (config->upperConfig->deviceSasToken != NULL)) ||
XinZhangMS 0:f7f1f0d76dd6 2396 //is_key_validate(config) != 0 ||
XinZhangMS 0:f7f1f0d76dd6 2397 config->upperConfig->iotHubName == NULL ||
XinZhangMS 0:f7f1f0d76dd6 2398 config->upperConfig->iotHubSuffix == NULL)
XinZhangMS 0:f7f1f0d76dd6 2399 {
XinZhangMS 0:f7f1f0d76dd6 2400 LogError("Invalid Argument: upperConfig structure contains an invalid parameter");
XinZhangMS 0:f7f1f0d76dd6 2401 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2402 }
XinZhangMS 0:f7f1f0d76dd6 2403 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_002: [If the parameter config's variables upperConfig, auth_module_handle or waitingToSend are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2404 else if (config->waitingToSend == NULL)
XinZhangMS 0:f7f1f0d76dd6 2405 {
XinZhangMS 0:f7f1f0d76dd6 2406 LogError("Invalid Argument: waitingToSend is NULL)");
XinZhangMS 0:f7f1f0d76dd6 2407 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2408 }
XinZhangMS 0:f7f1f0d76dd6 2409 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2410 else if (((deviceIdSize = strlen(config->upperConfig->deviceId)) > 128U) || (deviceIdSize == 0))
XinZhangMS 0:f7f1f0d76dd6 2411 {
XinZhangMS 0:f7f1f0d76dd6 2412 LogError("Invalid Argument: DeviceId is of an invalid size");
XinZhangMS 0:f7f1f0d76dd6 2413 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2414 }
XinZhangMS 0:f7f1f0d76dd6 2415 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2416 else if ((config->upperConfig->deviceKey != NULL) && (strlen(config->upperConfig->deviceKey) == 0))
XinZhangMS 0:f7f1f0d76dd6 2417 {
XinZhangMS 0:f7f1f0d76dd6 2418 LogError("Invalid Argument: deviceKey is empty");
XinZhangMS 0:f7f1f0d76dd6 2419 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2420 }
XinZhangMS 0:f7f1f0d76dd6 2421 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2422 else if ((config->upperConfig->deviceSasToken != NULL) && (strlen(config->upperConfig->deviceSasToken) == 0))
XinZhangMS 0:f7f1f0d76dd6 2423 {
XinZhangMS 0:f7f1f0d76dd6 2424 LogError("Invalid Argument: deviceSasToken is empty");
XinZhangMS 0:f7f1f0d76dd6 2425 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2426 }
XinZhangMS 0:f7f1f0d76dd6 2427 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_003: [If the upperConfig's variables deviceId, deviceKey, iotHubName, protocol, or iotHubSuffix are NULL then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2428 else if (strlen(config->upperConfig->iotHubName) == 0)
XinZhangMS 0:f7f1f0d76dd6 2429 {
XinZhangMS 0:f7f1f0d76dd6 2430 LogError("Invalid Argument: iotHubName is empty");
XinZhangMS 0:f7f1f0d76dd6 2431 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 2432 }
XinZhangMS 0:f7f1f0d76dd6 2433 else
XinZhangMS 0:f7f1f0d76dd6 2434 {
XinZhangMS 0:f7f1f0d76dd6 2435 result = InitializeTransportHandleData(config->upperConfig, config->waitingToSend, config->auth_module_handle, config->moduleId);
XinZhangMS 0:f7f1f0d76dd6 2436 if (result != NULL)
XinZhangMS 0:f7f1f0d76dd6 2437 {
XinZhangMS 0:f7f1f0d76dd6 2438 result->get_io_transport = get_io_transport;
XinZhangMS 0:f7f1f0d76dd6 2439 result->http_proxy_hostname = NULL;
XinZhangMS 0:f7f1f0d76dd6 2440 result->http_proxy_username = NULL;
XinZhangMS 0:f7f1f0d76dd6 2441 result->http_proxy_password = NULL;
XinZhangMS 0:f7f1f0d76dd6 2442 }
XinZhangMS 0:f7f1f0d76dd6 2443 }
XinZhangMS 0:f7f1f0d76dd6 2444 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_009: [If any error is encountered then IoTHubTransport_MQTT_Common_Create shall return NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2445 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_011: [On Success IoTHubTransport_MQTT_Common_Create shall return a non-NULL value.] */
XinZhangMS 0:f7f1f0d76dd6 2446 return result;
XinZhangMS 0:f7f1f0d76dd6 2447 }
XinZhangMS 0:f7f1f0d76dd6 2448
XinZhangMS 0:f7f1f0d76dd6 2449 void IoTHubTransport_MQTT_Common_Destroy(TRANSPORT_LL_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2450 {
XinZhangMS 0:f7f1f0d76dd6 2451 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_012: [IoTHubTransport_MQTT_Common_Destroy shall do nothing if parameter handle is NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2452 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2453 if (transport_data != NULL)
XinZhangMS 0:f7f1f0d76dd6 2454 {
XinZhangMS 0:f7f1f0d76dd6 2455 transport_data->isDestroyCalled = true;
XinZhangMS 0:f7f1f0d76dd6 2456
XinZhangMS 0:f7f1f0d76dd6 2457 DisconnectFromClient(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2458
XinZhangMS 0:f7f1f0d76dd6 2459 //Empty the Waiting for Ack Messages.
XinZhangMS 0:f7f1f0d76dd6 2460 while (!DList_IsListEmpty(&transport_data->telemetry_waitingForAck))
XinZhangMS 0:f7f1f0d76dd6 2461 {
XinZhangMS 0:f7f1f0d76dd6 2462 PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transport_data->telemetry_waitingForAck);
XinZhangMS 0:f7f1f0d76dd6 2463 MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentEntry, MQTT_MESSAGE_DETAILS_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 2464 sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_BECAUSE_DESTROY);
XinZhangMS 0:f7f1f0d76dd6 2465 free(mqttMsgEntry);
XinZhangMS 0:f7f1f0d76dd6 2466 }
XinZhangMS 0:f7f1f0d76dd6 2467 while (!DList_IsListEmpty(&transport_data->ack_waiting_queue))
XinZhangMS 0:f7f1f0d76dd6 2468 {
XinZhangMS 0:f7f1f0d76dd6 2469 PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transport_data->ack_waiting_queue);
XinZhangMS 0:f7f1f0d76dd6 2470 MQTT_DEVICE_TWIN_ITEM* mqtt_device_twin = containingRecord(currentEntry, MQTT_DEVICE_TWIN_ITEM, entry);
XinZhangMS 0:f7f1f0d76dd6 2471 IoTHubClientCore_LL_ReportedStateComplete(transport_data->llClientHandle, mqtt_device_twin->iothub_msg_id, STATUS_CODE_TIMEOUT_VALUE);
XinZhangMS 0:f7f1f0d76dd6 2472 free(mqtt_device_twin);
XinZhangMS 0:f7f1f0d76dd6 2473 }
XinZhangMS 0:f7f1f0d76dd6 2474
XinZhangMS 0:f7f1f0d76dd6 2475 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransport_MQTT_Common_Destroy shall free all the resources currently in use.] */
XinZhangMS 0:f7f1f0d76dd6 2476 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_012: [ `IoTHubTransport_MQTT_Common_Destroy` shall free the stored proxy options. ]*/
XinZhangMS 0:f7f1f0d76dd6 2477 free_transport_handle_data(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2478 }
XinZhangMS 0:f7f1f0d76dd6 2479 }
XinZhangMS 0:f7f1f0d76dd6 2480
XinZhangMS 0:f7f1f0d76dd6 2481 int IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2482 {
XinZhangMS 0:f7f1f0d76dd6 2483 int result;
XinZhangMS 0:f7f1f0d76dd6 2484 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2485 if (transport_data == NULL)
XinZhangMS 0:f7f1f0d76dd6 2486 {
XinZhangMS 0:f7f1f0d76dd6 2487 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_042: [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 2488 LogError("Invalid handle parameter. NULL.");
XinZhangMS 0:f7f1f0d76dd6 2489 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2490 }
XinZhangMS 0:f7f1f0d76dd6 2491 else
XinZhangMS 0:f7f1f0d76dd6 2492 {
XinZhangMS 0:f7f1f0d76dd6 2493 if (transport_data->topic_GetState == NULL)
XinZhangMS 0:f7f1f0d76dd6 2494 {
XinZhangMS 0:f7f1f0d76dd6 2495 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2496 transport_data->topic_GetState = STRING_construct(TOPIC_GET_DESIRED_STATE);
XinZhangMS 0:f7f1f0d76dd6 2497 if (transport_data->topic_GetState == NULL)
XinZhangMS 0:f7f1f0d76dd6 2498 {
XinZhangMS 0:f7f1f0d76dd6 2499 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_046: [Upon failure IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin shall return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 2500 LogError("Failure: unable constructing reported state topic");
XinZhangMS 0:f7f1f0d76dd6 2501 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2502 }
XinZhangMS 0:f7f1f0d76dd6 2503 else
XinZhangMS 0:f7f1f0d76dd6 2504 {
XinZhangMS 0:f7f1f0d76dd6 2505 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_047: [On success IoTHubTransport_MQTT_Common_Subscribe_DeviceTwin shall return 0.] */
XinZhangMS 0:f7f1f0d76dd6 2506 transport_data->topics_ToSubscribe |= SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2507 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2508 }
XinZhangMS 0:f7f1f0d76dd6 2509 }
XinZhangMS 0:f7f1f0d76dd6 2510 else
XinZhangMS 0:f7f1f0d76dd6 2511 {
XinZhangMS 0:f7f1f0d76dd6 2512 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2513 }
XinZhangMS 0:f7f1f0d76dd6 2514 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 2515 {
XinZhangMS 0:f7f1f0d76dd6 2516 changeStateToSubscribeIfAllowed(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2517 }
XinZhangMS 0:f7f1f0d76dd6 2518 }
XinZhangMS 0:f7f1f0d76dd6 2519 return result;
XinZhangMS 0:f7f1f0d76dd6 2520 }
XinZhangMS 0:f7f1f0d76dd6 2521
XinZhangMS 0:f7f1f0d76dd6 2522 void IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2523 {
XinZhangMS 0:f7f1f0d76dd6 2524 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2525 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_048: [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin shall do nothing.] */
XinZhangMS 0:f7f1f0d76dd6 2526 if (transport_data != NULL)
XinZhangMS 0:f7f1f0d76dd6 2527 {
XinZhangMS 0:f7f1f0d76dd6 2528 if (transport_data->topic_GetState != NULL)
XinZhangMS 0:f7f1f0d76dd6 2529 {
XinZhangMS 0:f7f1f0d76dd6 2530 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_049: [If subscribe_state is set to IOTHUB_DEVICE_TWIN_DESIRED_STATE then IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin shall unsubscribe from the topic_GetState to the mqtt client.] */
XinZhangMS 0:f7f1f0d76dd6 2531 transport_data->topics_ToSubscribe &= ~SUBSCRIBE_GET_REPORTED_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2532 STRING_delete(transport_data->topic_GetState);
XinZhangMS 0:f7f1f0d76dd6 2533 transport_data->topic_GetState = NULL;
XinZhangMS 0:f7f1f0d76dd6 2534 }
XinZhangMS 0:f7f1f0d76dd6 2535 if (transport_data->topic_NotifyState != NULL)
XinZhangMS 0:f7f1f0d76dd6 2536 {
XinZhangMS 0:f7f1f0d76dd6 2537 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_050: [If subscribe_state is set to IOTHUB_DEVICE_TWIN_NOTIFICATION_STATE then IoTHubTransport_MQTT_Common_Unsubscribe_DeviceTwin shall unsubscribe from the topic_NotifyState to the mqtt client.] */
XinZhangMS 0:f7f1f0d76dd6 2538 transport_data->topics_ToSubscribe &= ~SUBSCRIBE_NOTIFICATION_STATE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2539 STRING_delete(transport_data->topic_NotifyState);
XinZhangMS 0:f7f1f0d76dd6 2540 transport_data->topic_NotifyState = NULL;
XinZhangMS 0:f7f1f0d76dd6 2541 }
XinZhangMS 0:f7f1f0d76dd6 2542 }
XinZhangMS 0:f7f1f0d76dd6 2543 else
XinZhangMS 0:f7f1f0d76dd6 2544 {
XinZhangMS 0:f7f1f0d76dd6 2545 LogError("Invalid argument to unsubscribe (handle is NULL).");
XinZhangMS 0:f7f1f0d76dd6 2546 }
XinZhangMS 0:f7f1f0d76dd6 2547 }
XinZhangMS 0:f7f1f0d76dd6 2548
XinZhangMS 0:f7f1f0d76dd6 2549 int IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2550 {
XinZhangMS 0:f7f1f0d76dd6 2551 int result;
XinZhangMS 0:f7f1f0d76dd6 2552 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2553
XinZhangMS 0:f7f1f0d76dd6 2554 if (transport_data == NULL)
XinZhangMS 0:f7f1f0d76dd6 2555 {
XinZhangMS 0:f7f1f0d76dd6 2556 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_001 : [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return a non - zero value.]*/
XinZhangMS 0:f7f1f0d76dd6 2557 LogError("Invalid handle parameter. NULL.");
XinZhangMS 0:f7f1f0d76dd6 2558 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2559 }
XinZhangMS 0:f7f1f0d76dd6 2560 else
XinZhangMS 0:f7f1f0d76dd6 2561 {
XinZhangMS 0:f7f1f0d76dd6 2562 if (transport_data->topic_DeviceMethods == NULL)
XinZhangMS 0:f7f1f0d76dd6 2563 {
XinZhangMS 0:f7f1f0d76dd6 2564 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_004 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall construct the DEVICE_METHOD topic string for subscribe.]*/
XinZhangMS 0:f7f1f0d76dd6 2565 transport_data->topic_DeviceMethods = STRING_construct(TOPIC_DEVICE_METHOD_SUBSCRIBE);
XinZhangMS 0:f7f1f0d76dd6 2566 if (transport_data->topic_DeviceMethods == NULL)
XinZhangMS 0:f7f1f0d76dd6 2567 {
XinZhangMS 0:f7f1f0d76dd6 2568 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_006 : [Upon failure IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return a non - zero value.]*/
XinZhangMS 0:f7f1f0d76dd6 2569 LogError("Failure: unable constructing device method subscribe topic");
XinZhangMS 0:f7f1f0d76dd6 2570 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2571 }
XinZhangMS 0:f7f1f0d76dd6 2572 else
XinZhangMS 0:f7f1f0d76dd6 2573 {
XinZhangMS 0:f7f1f0d76dd6 2574 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_003 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall set the signaling flag for DEVICE_METHOD topic for the receiver's topic list. ]*/
XinZhangMS 0:f7f1f0d76dd6 2575 transport_data->topics_ToSubscribe |= SUBSCRIBE_DEVICE_METHOD_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2576 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2577 }
XinZhangMS 0:f7f1f0d76dd6 2578 }
XinZhangMS 0:f7f1f0d76dd6 2579 else
XinZhangMS 0:f7f1f0d76dd6 2580 {
XinZhangMS 0:f7f1f0d76dd6 2581 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_002 : [If the MQTT transport has been previously subscribed to DEVICE_METHOD topic IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall do nothing and return 0.]*/
XinZhangMS 0:f7f1f0d76dd6 2582 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2583 }
XinZhangMS 0:f7f1f0d76dd6 2584
XinZhangMS 0:f7f1f0d76dd6 2585 if (result == 0)
XinZhangMS 0:f7f1f0d76dd6 2586 {
XinZhangMS 0:f7f1f0d76dd6 2587 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_005 : [IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall schedule the send of the subscription.]*/
XinZhangMS 0:f7f1f0d76dd6 2588 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_007 : [On success IoTHubTransport_MQTT_Common_Subscribe_DeviceMethod shall return 0.]*/
XinZhangMS 0:f7f1f0d76dd6 2589 changeStateToSubscribeIfAllowed(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2590 }
XinZhangMS 0:f7f1f0d76dd6 2591 }
XinZhangMS 0:f7f1f0d76dd6 2592 return result;
XinZhangMS 0:f7f1f0d76dd6 2593 }
XinZhangMS 0:f7f1f0d76dd6 2594
XinZhangMS 0:f7f1f0d76dd6 2595 void IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2596 {
XinZhangMS 0:f7f1f0d76dd6 2597 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2598 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_008 : [If the parameter handle is NULL than IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall do nothing and return.]*/
XinZhangMS 0:f7f1f0d76dd6 2599 if (transport_data != NULL)
XinZhangMS 0:f7f1f0d76dd6 2600 {
XinZhangMS 0:f7f1f0d76dd6 2601 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_009 : [If the MQTT transport has not been subscribed to DEVICE_METHOD topic IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall do nothing and return.]*/
XinZhangMS 0:f7f1f0d76dd6 2602 if (transport_data->topic_DeviceMethods != NULL)
XinZhangMS 0:f7f1f0d76dd6 2603 {
XinZhangMS 0:f7f1f0d76dd6 2604 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_010 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall construct the DEVICE_METHOD topic string for unsubscribe.]*/
XinZhangMS 0:f7f1f0d76dd6 2605 const char* unsubscribe[1];
XinZhangMS 0:f7f1f0d76dd6 2606 unsubscribe[0] = STRING_c_str(transport_data->topic_DeviceMethods);
XinZhangMS 0:f7f1f0d76dd6 2607
XinZhangMS 0:f7f1f0d76dd6 2608 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_011 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall send the unsubscribe.]*/
XinZhangMS 0:f7f1f0d76dd6 2609 if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
XinZhangMS 0:f7f1f0d76dd6 2610 {
XinZhangMS 0:f7f1f0d76dd6 2611 LogError("Failure calling mqtt_client_unsubscribe");
XinZhangMS 0:f7f1f0d76dd6 2612 }
XinZhangMS 0:f7f1f0d76dd6 2613
XinZhangMS 0:f7f1f0d76dd6 2614 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_12_012 : [IoTHubTransport_MQTT_Common_Unsubscribe_DeviceMethod shall removes the signaling flag for DEVICE_METHOD topic from the receiver's topic list. ]*/
XinZhangMS 0:f7f1f0d76dd6 2615 STRING_delete(transport_data->topic_DeviceMethods);
XinZhangMS 0:f7f1f0d76dd6 2616 transport_data->topic_DeviceMethods = NULL;
XinZhangMS 0:f7f1f0d76dd6 2617 transport_data->topics_ToSubscribe &= ~SUBSCRIBE_DEVICE_METHOD_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2618 }
XinZhangMS 0:f7f1f0d76dd6 2619 }
XinZhangMS 0:f7f1f0d76dd6 2620 else
XinZhangMS 0:f7f1f0d76dd6 2621 {
XinZhangMS 0:f7f1f0d76dd6 2622 LogError("Invalid argument to unsubscribe (NULL).");
XinZhangMS 0:f7f1f0d76dd6 2623 }
XinZhangMS 0:f7f1f0d76dd6 2624 }
XinZhangMS 0:f7f1f0d76dd6 2625
XinZhangMS 0:f7f1f0d76dd6 2626 int IoTHubTransport_MQTT_Common_DeviceMethod_Response(IOTHUB_DEVICE_HANDLE handle, METHOD_HANDLE methodId, const unsigned char* response, size_t respSize, int status)
XinZhangMS 0:f7f1f0d76dd6 2627 {
XinZhangMS 0:f7f1f0d76dd6 2628 int result;
XinZhangMS 0:f7f1f0d76dd6 2629 MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 2630 if (transport_data != NULL)
XinZhangMS 0:f7f1f0d76dd6 2631 {
XinZhangMS 0:f7f1f0d76dd6 2632 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_042: [ IoTHubTransport_MQTT_Common_DeviceMethod_Response shall publish an mqtt message for the device method response. ] */
XinZhangMS 0:f7f1f0d76dd6 2633 DEVICE_METHOD_INFO* dev_method_info = (DEVICE_METHOD_INFO*)methodId;
XinZhangMS 0:f7f1f0d76dd6 2634 if (dev_method_info == NULL)
XinZhangMS 0:f7f1f0d76dd6 2635 {
XinZhangMS 0:f7f1f0d76dd6 2636 LogError("Failure: DEVICE_METHOD_INFO was NULL");
XinZhangMS 0:f7f1f0d76dd6 2637 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2638 }
XinZhangMS 0:f7f1f0d76dd6 2639 else
XinZhangMS 0:f7f1f0d76dd6 2640 {
XinZhangMS 0:f7f1f0d76dd6 2641 if (publish_device_method_message(transport_data, status, dev_method_info->request_id, response, respSize) != 0)
XinZhangMS 0:f7f1f0d76dd6 2642 {
XinZhangMS 0:f7f1f0d76dd6 2643 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_051: [ If any error is encountered, IoTHubTransport_MQTT_Common_DeviceMethod_Response shall return a non-zero value. ] */
XinZhangMS 0:f7f1f0d76dd6 2644 LogError("Failure: publishing device method response");
XinZhangMS 0:f7f1f0d76dd6 2645 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2646 }
XinZhangMS 0:f7f1f0d76dd6 2647 else
XinZhangMS 0:f7f1f0d76dd6 2648 {
XinZhangMS 0:f7f1f0d76dd6 2649 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2650 }
XinZhangMS 0:f7f1f0d76dd6 2651 STRING_delete(dev_method_info->request_id);
XinZhangMS 0:f7f1f0d76dd6 2652 free(dev_method_info);
XinZhangMS 0:f7f1f0d76dd6 2653 }
XinZhangMS 0:f7f1f0d76dd6 2654 }
XinZhangMS 0:f7f1f0d76dd6 2655 else
XinZhangMS 0:f7f1f0d76dd6 2656 {
XinZhangMS 0:f7f1f0d76dd6 2657 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_041: [ If the parameter handle is NULL than IoTHubTransport_MQTT_Common_DeviceMethod_Response shall return a non-zero value. ] */
XinZhangMS 0:f7f1f0d76dd6 2658 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2659 LogError("Failure: invalid IOTHUB_DEVICE_HANDLE parameter specified");
XinZhangMS 0:f7f1f0d76dd6 2660 }
XinZhangMS 0:f7f1f0d76dd6 2661 return result;
XinZhangMS 0:f7f1f0d76dd6 2662 }
XinZhangMS 0:f7f1f0d76dd6 2663
XinZhangMS 0:f7f1f0d76dd6 2664 static STRING_HANDLE buildTopicMqttMessage(const char* device_id, const char* module_id)
XinZhangMS 0:f7f1f0d76dd6 2665 {
XinZhangMS 0:f7f1f0d76dd6 2666 if (module_id == NULL)
XinZhangMS 0:f7f1f0d76dd6 2667 {
XinZhangMS 0:f7f1f0d76dd6 2668 return STRING_construct_sprintf(TOPIC_DEVICE_MSG, device_id);
XinZhangMS 0:f7f1f0d76dd6 2669 }
XinZhangMS 0:f7f1f0d76dd6 2670 else
XinZhangMS 0:f7f1f0d76dd6 2671 {
XinZhangMS 0:f7f1f0d76dd6 2672 return STRING_construct_sprintf(TOPIC_DEVICE_MODULE_MSG, device_id, module_id);
XinZhangMS 0:f7f1f0d76dd6 2673 }
XinZhangMS 0:f7f1f0d76dd6 2674 }
XinZhangMS 0:f7f1f0d76dd6 2675
XinZhangMS 0:f7f1f0d76dd6 2676 int IoTHubTransport_MQTT_Common_Subscribe(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2677 {
XinZhangMS 0:f7f1f0d76dd6 2678 int result;
XinZhangMS 0:f7f1f0d76dd6 2679 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2680 if (transport_data == NULL)
XinZhangMS 0:f7f1f0d76dd6 2681 {
XinZhangMS 0:f7f1f0d76dd6 2682 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_015: [If parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe shall return a non-zero value.] */
XinZhangMS 0:f7f1f0d76dd6 2683 LogError("Invalid handle parameter. NULL.");
XinZhangMS 0:f7f1f0d76dd6 2684 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2685 }
XinZhangMS 0:f7f1f0d76dd6 2686 else
XinZhangMS 0:f7f1f0d76dd6 2687 {
XinZhangMS 0:f7f1f0d76dd6 2688 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 2689 transport_data->topic_MqttMessage = buildTopicMqttMessage(STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id));
XinZhangMS 0:f7f1f0d76dd6 2690 if (transport_data->topic_MqttMessage == NULL)
XinZhangMS 0:f7f1f0d76dd6 2691 {
XinZhangMS 0:f7f1f0d76dd6 2692 LogError("Failure constructing Message Topic");
XinZhangMS 0:f7f1f0d76dd6 2693 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 2694 }
XinZhangMS 0:f7f1f0d76dd6 2695 else
XinZhangMS 0:f7f1f0d76dd6 2696 {
XinZhangMS 0:f7f1f0d76dd6 2697 transport_data->topics_ToSubscribe |= SUBSCRIBE_TELEMETRY_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2698 /* 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.]*/
XinZhangMS 0:f7f1f0d76dd6 2699 changeStateToSubscribeIfAllowed(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2700 result = 0;
XinZhangMS 0:f7f1f0d76dd6 2701 }
XinZhangMS 0:f7f1f0d76dd6 2702 }
XinZhangMS 0:f7f1f0d76dd6 2703 return result;
XinZhangMS 0:f7f1f0d76dd6 2704 }
XinZhangMS 0:f7f1f0d76dd6 2705
XinZhangMS 0:f7f1f0d76dd6 2706 void IoTHubTransport_MQTT_Common_Unsubscribe(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 2707 {
XinZhangMS 0:f7f1f0d76dd6 2708 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2709 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_019: [If parameter handle is NULL then IoTHubTransport_MQTT_Common_Unsubscribe shall do nothing.] */
XinZhangMS 0:f7f1f0d76dd6 2710 if (transport_data != NULL)
XinZhangMS 0:f7f1f0d76dd6 2711 {
XinZhangMS 0:f7f1f0d76dd6 2712 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_020: [IoTHubTransport_MQTT_Common_Unsubscribe shall call mqtt_client_unsubscribe to unsubscribe the mqtt message topic.] */
XinZhangMS 0:f7f1f0d76dd6 2713 const char* unsubscribe[1];
XinZhangMS 0:f7f1f0d76dd6 2714 unsubscribe[0] = STRING_c_str(transport_data->topic_MqttMessage);
XinZhangMS 0:f7f1f0d76dd6 2715 if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
XinZhangMS 0:f7f1f0d76dd6 2716 {
XinZhangMS 0:f7f1f0d76dd6 2717 LogError("Failure calling mqtt_client_unsubscribe");
XinZhangMS 0:f7f1f0d76dd6 2718 }
XinZhangMS 0:f7f1f0d76dd6 2719 STRING_delete(transport_data->topic_MqttMessage);
XinZhangMS 0:f7f1f0d76dd6 2720 transport_data->topic_MqttMessage = NULL;
XinZhangMS 0:f7f1f0d76dd6 2721 transport_data->topics_ToSubscribe &= ~SUBSCRIBE_TELEMETRY_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 2722 }
XinZhangMS 0:f7f1f0d76dd6 2723 else
XinZhangMS 0:f7f1f0d76dd6 2724 {
XinZhangMS 0:f7f1f0d76dd6 2725 LogError("Invalid argument to unsubscribe (NULL).");
XinZhangMS 0:f7f1f0d76dd6 2726 }
XinZhangMS 0:f7f1f0d76dd6 2727 }
XinZhangMS 0:f7f1f0d76dd6 2728
XinZhangMS 0:f7f1f0d76dd6 2729 IOTHUB_PROCESS_ITEM_RESULT IoTHubTransport_MQTT_Common_ProcessItem(TRANSPORT_LL_HANDLE handle, IOTHUB_IDENTITY_TYPE item_type, IOTHUB_IDENTITY_INFO* iothub_item)
XinZhangMS 0:f7f1f0d76dd6 2730 {
XinZhangMS 0:f7f1f0d76dd6 2731 IOTHUB_PROCESS_ITEM_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 2732 /* Codes_SRS_IOTHUBCLIENT_LL_07_001: [ If handle or iothub_item are NULL then IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 2733 if (handle == NULL || iothub_item == NULL)
XinZhangMS 0:f7f1f0d76dd6 2734 {
XinZhangMS 0:f7f1f0d76dd6 2735 LogError("Invalid handle parameter iothub_item=%p", iothub_item);
XinZhangMS 0:f7f1f0d76dd6 2736 result = IOTHUB_PROCESS_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2737 }
XinZhangMS 0:f7f1f0d76dd6 2738 else
XinZhangMS 0:f7f1f0d76dd6 2739 {
XinZhangMS 0:f7f1f0d76dd6 2740 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2741
XinZhangMS 0:f7f1f0d76dd6 2742 if (transport_data->currPacketState == PUBLISH_TYPE)
XinZhangMS 0:f7f1f0d76dd6 2743 {
XinZhangMS 0:f7f1f0d76dd6 2744 if (item_type == IOTHUB_TYPE_DEVICE_TWIN)
XinZhangMS 0:f7f1f0d76dd6 2745 {
XinZhangMS 0:f7f1f0d76dd6 2746 MQTT_DEVICE_TWIN_ITEM* mqtt_info = (MQTT_DEVICE_TWIN_ITEM*)malloc(sizeof(MQTT_DEVICE_TWIN_ITEM));
XinZhangMS 0:f7f1f0d76dd6 2747 if (mqtt_info == NULL)
XinZhangMS 0:f7f1f0d76dd6 2748 {
XinZhangMS 0:f7f1f0d76dd6 2749 /* Codes_SRS_IOTHUBCLIENT_LL_07_004: [ If any errors are encountered IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 2750 result = IOTHUB_PROCESS_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2751 }
XinZhangMS 0:f7f1f0d76dd6 2752 else
XinZhangMS 0:f7f1f0d76dd6 2753 {
XinZhangMS 0:f7f1f0d76dd6 2754 /*Codes_SRS_IOTHUBCLIENT_LL_07_003: [ IoTHubTransport_MQTT_Common_ProcessItem shall publish a message to the mqtt protocol with the message topic for the message type.]*/
XinZhangMS 0:f7f1f0d76dd6 2755 mqtt_info->iothub_type = item_type;
XinZhangMS 0:f7f1f0d76dd6 2756 mqtt_info->iothub_msg_id = iothub_item->device_twin->item_id;
XinZhangMS 0:f7f1f0d76dd6 2757 mqtt_info->retryCount = 0;
XinZhangMS 0:f7f1f0d76dd6 2758
XinZhangMS 0:f7f1f0d76dd6 2759 /* Codes_SRS_IOTHUBCLIENT_LL_07_005: [ If successful IoTHubTransport_MQTT_Common_ProcessItem shall add mqtt info structure acknowledgement queue. ] */
XinZhangMS 0:f7f1f0d76dd6 2760 DList_InsertTailList(&transport_data->ack_waiting_queue, &mqtt_info->entry);
XinZhangMS 0:f7f1f0d76dd6 2761
XinZhangMS 0:f7f1f0d76dd6 2762 if (publish_device_twin_message(transport_data, iothub_item->device_twin, mqtt_info) != 0)
XinZhangMS 0:f7f1f0d76dd6 2763 {
XinZhangMS 0:f7f1f0d76dd6 2764 DList_RemoveEntryList(&mqtt_info->entry);
XinZhangMS 0:f7f1f0d76dd6 2765
XinZhangMS 0:f7f1f0d76dd6 2766 free(mqtt_info);
XinZhangMS 0:f7f1f0d76dd6 2767 /* Codes_SRS_IOTHUBCLIENT_LL_07_004: [ If any errors are encountered IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 2768 result = IOTHUB_PROCESS_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2769 }
XinZhangMS 0:f7f1f0d76dd6 2770 else
XinZhangMS 0:f7f1f0d76dd6 2771 {
XinZhangMS 0:f7f1f0d76dd6 2772 result = IOTHUB_PROCESS_OK;
XinZhangMS 0:f7f1f0d76dd6 2773 }
XinZhangMS 0:f7f1f0d76dd6 2774 }
XinZhangMS 0:f7f1f0d76dd6 2775 }
XinZhangMS 0:f7f1f0d76dd6 2776 else
XinZhangMS 0:f7f1f0d76dd6 2777 {
XinZhangMS 0:f7f1f0d76dd6 2778 /* Codes_SRS_IOTHUBCLIENT_LL_07_006: [ If the item_type is not a supported type IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_CONTINUE. ]*/
XinZhangMS 0:f7f1f0d76dd6 2779 result = IOTHUB_PROCESS_CONTINUE;
XinZhangMS 0:f7f1f0d76dd6 2780 }
XinZhangMS 0:f7f1f0d76dd6 2781 }
XinZhangMS 0:f7f1f0d76dd6 2782 else
XinZhangMS 0:f7f1f0d76dd6 2783 {
XinZhangMS 0:f7f1f0d76dd6 2784 /* Codes_SRS_IOTHUBCLIENT_LL_07_002: [ If the mqtt is not ready to publish messages IoTHubTransport_MQTT_Common_ProcessItem shall return IOTHUB_PROCESS_NOT_CONNECTED. ] */
XinZhangMS 0:f7f1f0d76dd6 2785 result = IOTHUB_PROCESS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 2786 }
XinZhangMS 0:f7f1f0d76dd6 2787 }
XinZhangMS 0:f7f1f0d76dd6 2788 return result;
XinZhangMS 0:f7f1f0d76dd6 2789 }
XinZhangMS 0:f7f1f0d76dd6 2790
XinZhangMS 0:f7f1f0d76dd6 2791 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_054: [ IoTHubTransport_MQTT_Common_DoWork shall subscribe to the Notification and get_state Topics if they are defined. ] */
XinZhangMS 0:f7f1f0d76dd6 2792 void IoTHubTransport_MQTT_Common_DoWork(TRANSPORT_LL_HANDLE handle, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle)
XinZhangMS 0:f7f1f0d76dd6 2793 {
XinZhangMS 0:f7f1f0d76dd6 2794 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransport_MQTT_Common_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */
XinZhangMS 0:f7f1f0d76dd6 2795 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 2796 if (transport_data != NULL && iotHubClientHandle != NULL)
XinZhangMS 0:f7f1f0d76dd6 2797 {
XinZhangMS 0:f7f1f0d76dd6 2798 transport_data->llClientHandle = iotHubClientHandle;
XinZhangMS 0:f7f1f0d76dd6 2799
XinZhangMS 0:f7f1f0d76dd6 2800 if (InitializeConnection(transport_data) != 0)
XinZhangMS 0:f7f1f0d76dd6 2801 {
XinZhangMS 0:f7f1f0d76dd6 2802 // Don't want to flood the logs with failures here
XinZhangMS 0:f7f1f0d76dd6 2803 }
XinZhangMS 0:f7f1f0d76dd6 2804 else
XinZhangMS 0:f7f1f0d76dd6 2805 {
XinZhangMS 0:f7f1f0d76dd6 2806 if (transport_data->mqttClientStatus == MQTT_CLIENT_STATUS_PENDING_CLOSE)
XinZhangMS 0:f7f1f0d76dd6 2807 {
XinZhangMS 0:f7f1f0d76dd6 2808 mqtt_client_disconnect(transport_data->mqttClient, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 2809 transport_data->mqttClientStatus = MQTT_CLIENT_STATUS_NOT_CONNECTED;
XinZhangMS 0:f7f1f0d76dd6 2810 }
XinZhangMS 0:f7f1f0d76dd6 2811 else if (transport_data->currPacketState == CONNACK_TYPE || transport_data->currPacketState == SUBSCRIBE_TYPE)
XinZhangMS 0:f7f1f0d76dd6 2812 {
XinZhangMS 0:f7f1f0d76dd6 2813 SubscribeToMqttProtocol(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2814 }
XinZhangMS 0:f7f1f0d76dd6 2815 else if (transport_data->currPacketState == SUBACK_TYPE)
XinZhangMS 0:f7f1f0d76dd6 2816 {
XinZhangMS 0:f7f1f0d76dd6 2817 if ((transport_data->topic_NotifyState != NULL || transport_data->topic_GetState != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 2818 !transport_data->device_twin_get_sent)
XinZhangMS 0:f7f1f0d76dd6 2819 {
XinZhangMS 0:f7f1f0d76dd6 2820 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_055: [ IoTHubTransport_MQTT_Common_DoWork shall send a device twin get property message upon successfully retrieving a SUBACK on device twin topics. ] */
XinZhangMS 0:f7f1f0d76dd6 2821 if (publish_device_twin_get_message(transport_data) == 0)
XinZhangMS 0:f7f1f0d76dd6 2822 {
XinZhangMS 0:f7f1f0d76dd6 2823 transport_data->device_twin_get_sent = true;
XinZhangMS 0:f7f1f0d76dd6 2824 }
XinZhangMS 0:f7f1f0d76dd6 2825 else
XinZhangMS 0:f7f1f0d76dd6 2826 {
XinZhangMS 0:f7f1f0d76dd6 2827 LogError("Failure: sending device twin get property command.");
XinZhangMS 0:f7f1f0d76dd6 2828 }
XinZhangMS 0:f7f1f0d76dd6 2829 }
XinZhangMS 0:f7f1f0d76dd6 2830 // Publish can be called now
XinZhangMS 0:f7f1f0d76dd6 2831 transport_data->currPacketState = PUBLISH_TYPE;
XinZhangMS 0:f7f1f0d76dd6 2832 }
XinZhangMS 0:f7f1f0d76dd6 2833 else if (transport_data->currPacketState == PUBLISH_TYPE)
XinZhangMS 0:f7f1f0d76dd6 2834 {
XinZhangMS 0:f7f1f0d76dd6 2835 PDLIST_ENTRY currentListEntry = transport_data->telemetry_waitingForAck.Flink;
XinZhangMS 0:f7f1f0d76dd6 2836 while (currentListEntry != &transport_data->telemetry_waitingForAck)
XinZhangMS 0:f7f1f0d76dd6 2837 {
XinZhangMS 0:f7f1f0d76dd6 2838 tickcounter_ms_t current_ms;
XinZhangMS 0:f7f1f0d76dd6 2839 MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentListEntry, MQTT_MESSAGE_DETAILS_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 2840 DLIST_ENTRY nextListEntry;
XinZhangMS 0:f7f1f0d76dd6 2841 nextListEntry.Flink = currentListEntry->Flink;
XinZhangMS 0:f7f1f0d76dd6 2842
XinZhangMS 0:f7f1f0d76dd6 2843 (void)tickcounter_get_current_ms(transport_data->msgTickCounter, &current_ms);
XinZhangMS 0:f7f1f0d76dd6 2844 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_033: [IoTHubTransport_MQTT_Common_DoWork shall iterate through the Waiting Acknowledge messages looking for any message that has been waiting longer than 2 min.]*/
XinZhangMS 0:f7f1f0d76dd6 2845 if (((current_ms - mqttMsgEntry->msgPublishTime) / 1000) > RESEND_TIMEOUT_VALUE_MIN)
XinZhangMS 0:f7f1f0d76dd6 2846 {
XinZhangMS 0:f7f1f0d76dd6 2847 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_034: [If IoTHubTransport_MQTT_Common_DoWork has resent the message two times then it shall fail the message and reconnect to IoTHub ... ] */
XinZhangMS 0:f7f1f0d76dd6 2848 if (mqttMsgEntry->retryCount >= MAX_SEND_RECOUNT_LIMIT)
XinZhangMS 0:f7f1f0d76dd6 2849 {
XinZhangMS 0:f7f1f0d76dd6 2850 PDLIST_ENTRY current_entry;
XinZhangMS 0:f7f1f0d76dd6 2851 (void)DList_RemoveEntryList(currentListEntry);
XinZhangMS 0:f7f1f0d76dd6 2852 sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_MESSAGE_TIMEOUT);
XinZhangMS 0:f7f1f0d76dd6 2853 free(mqttMsgEntry);
XinZhangMS 0:f7f1f0d76dd6 2854
XinZhangMS 0:f7f1f0d76dd6 2855 transport_data->currPacketState = PACKET_TYPE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 2856 transport_data->device_twin_get_sent = false;
XinZhangMS 0:f7f1f0d76dd6 2857 DisconnectFromClient(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2858
XinZhangMS 0:f7f1f0d76dd6 2859 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_057: [ ... then go through all the rest of the waiting messages and reset the retryCount on the message. ]*/
XinZhangMS 0:f7f1f0d76dd6 2860 current_entry = transport_data->telemetry_waitingForAck.Flink;
XinZhangMS 0:f7f1f0d76dd6 2861 while (current_entry != &transport_data->telemetry_waitingForAck)
XinZhangMS 0:f7f1f0d76dd6 2862 {
XinZhangMS 0:f7f1f0d76dd6 2863 MQTT_MESSAGE_DETAILS_LIST* msg_reset_entry;
XinZhangMS 0:f7f1f0d76dd6 2864 msg_reset_entry = containingRecord(current_entry, MQTT_MESSAGE_DETAILS_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 2865 msg_reset_entry->retryCount = 0;
XinZhangMS 0:f7f1f0d76dd6 2866 current_entry = current_entry->Flink;
XinZhangMS 0:f7f1f0d76dd6 2867 }
XinZhangMS 0:f7f1f0d76dd6 2868 }
XinZhangMS 0:f7f1f0d76dd6 2869 else
XinZhangMS 0:f7f1f0d76dd6 2870 {
XinZhangMS 0:f7f1f0d76dd6 2871 size_t messageLength;
XinZhangMS 0:f7f1f0d76dd6 2872 const unsigned char* messagePayload = RetrieveMessagePayload(mqttMsgEntry->iotHubMessageEntry->messageHandle, &messageLength);
XinZhangMS 0:f7f1f0d76dd6 2873 if (messageLength == 0 || messagePayload == NULL)
XinZhangMS 0:f7f1f0d76dd6 2874 {
XinZhangMS 0:f7f1f0d76dd6 2875 LogError("Failure from creating Message IoTHubMessage_GetData");
XinZhangMS 0:f7f1f0d76dd6 2876 }
XinZhangMS 0:f7f1f0d76dd6 2877 else
XinZhangMS 0:f7f1f0d76dd6 2878 {
XinZhangMS 0:f7f1f0d76dd6 2879 if (publish_mqtt_telemetry_msg(transport_data, mqttMsgEntry, messagePayload, messageLength) != 0)
XinZhangMS 0:f7f1f0d76dd6 2880 {
XinZhangMS 0:f7f1f0d76dd6 2881 (void)DList_RemoveEntryList(currentListEntry);
XinZhangMS 0:f7f1f0d76dd6 2882 sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
XinZhangMS 0:f7f1f0d76dd6 2883 free(mqttMsgEntry);
XinZhangMS 0:f7f1f0d76dd6 2884 }
XinZhangMS 0:f7f1f0d76dd6 2885 }
XinZhangMS 0:f7f1f0d76dd6 2886 }
XinZhangMS 0:f7f1f0d76dd6 2887 }
XinZhangMS 0:f7f1f0d76dd6 2888 currentListEntry = nextListEntry.Flink;
XinZhangMS 0:f7f1f0d76dd6 2889 }
XinZhangMS 0:f7f1f0d76dd6 2890
XinZhangMS 0:f7f1f0d76dd6 2891 currentListEntry = transport_data->waitingToSend->Flink;
XinZhangMS 0:f7f1f0d76dd6 2892 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
XinZhangMS 0:f7f1f0d76dd6 2893 while (currentListEntry != transport_data->waitingToSend)
XinZhangMS 0:f7f1f0d76dd6 2894 {
XinZhangMS 0:f7f1f0d76dd6 2895 IOTHUB_MESSAGE_LIST* iothubMsgList = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry);
XinZhangMS 0:f7f1f0d76dd6 2896 DLIST_ENTRY savedFromCurrentListEntry;
XinZhangMS 0:f7f1f0d76dd6 2897 savedFromCurrentListEntry.Flink = currentListEntry->Flink;
XinZhangMS 0:f7f1f0d76dd6 2898
XinZhangMS 0:f7f1f0d76dd6 2899 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransport_MQTT_Common_DoWork shall inspect the "waitingToSend" DLIST passed in config structure.] */
XinZhangMS 0:f7f1f0d76dd6 2900 size_t messageLength;
XinZhangMS 0:f7f1f0d76dd6 2901 const unsigned char* messagePayload = RetrieveMessagePayload(iothubMsgList->messageHandle, &messageLength);
XinZhangMS 0:f7f1f0d76dd6 2902 if (messageLength == 0 || messagePayload == NULL)
XinZhangMS 0:f7f1f0d76dd6 2903 {
XinZhangMS 0:f7f1f0d76dd6 2904 LogError("Failure result from IoTHubMessage_GetData");
XinZhangMS 0:f7f1f0d76dd6 2905 }
XinZhangMS 0:f7f1f0d76dd6 2906 else
XinZhangMS 0:f7f1f0d76dd6 2907 {
XinZhangMS 0:f7f1f0d76dd6 2908 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransport_MQTT_Common_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */
XinZhangMS 0:f7f1f0d76dd6 2909 MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = (MQTT_MESSAGE_DETAILS_LIST*)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST));
XinZhangMS 0:f7f1f0d76dd6 2910 if (mqttMsgEntry == NULL)
XinZhangMS 0:f7f1f0d76dd6 2911 {
XinZhangMS 0:f7f1f0d76dd6 2912 LogError("Allocation Error: Failure allocating MQTT Message Detail List.");
XinZhangMS 0:f7f1f0d76dd6 2913 }
XinZhangMS 0:f7f1f0d76dd6 2914 else
XinZhangMS 0:f7f1f0d76dd6 2915 {
XinZhangMS 0:f7f1f0d76dd6 2916 mqttMsgEntry->retryCount = 0;
XinZhangMS 0:f7f1f0d76dd6 2917 mqttMsgEntry->iotHubMessageEntry = iothubMsgList;
XinZhangMS 0:f7f1f0d76dd6 2918 mqttMsgEntry->packet_id = get_next_packet_id(transport_data);
XinZhangMS 0:f7f1f0d76dd6 2919 if (publish_mqtt_telemetry_msg(transport_data, mqttMsgEntry, messagePayload, messageLength) != 0)
XinZhangMS 0:f7f1f0d76dd6 2920 {
XinZhangMS 0:f7f1f0d76dd6 2921 (void)(DList_RemoveEntryList(currentListEntry));
XinZhangMS 0:f7f1f0d76dd6 2922 sendMsgComplete(iothubMsgList, transport_data, IOTHUB_CLIENT_CONFIRMATION_ERROR);
XinZhangMS 0:f7f1f0d76dd6 2923 free(mqttMsgEntry);
XinZhangMS 0:f7f1f0d76dd6 2924 }
XinZhangMS 0:f7f1f0d76dd6 2925 else
XinZhangMS 0:f7f1f0d76dd6 2926 {
XinZhangMS 0:f7f1f0d76dd6 2927 (void)(DList_RemoveEntryList(currentListEntry));
XinZhangMS 0:f7f1f0d76dd6 2928 DList_InsertTailList(&(transport_data->telemetry_waitingForAck), &(mqttMsgEntry->entry));
XinZhangMS 0:f7f1f0d76dd6 2929 }
XinZhangMS 0:f7f1f0d76dd6 2930 }
XinZhangMS 0:f7f1f0d76dd6 2931 }
XinZhangMS 0:f7f1f0d76dd6 2932 currentListEntry = savedFromCurrentListEntry.Flink;
XinZhangMS 0:f7f1f0d76dd6 2933 }
XinZhangMS 0:f7f1f0d76dd6 2934 }
XinZhangMS 0:f7f1f0d76dd6 2935 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransport_MQTT_Common_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */
XinZhangMS 0:f7f1f0d76dd6 2936 mqtt_client_dowork(transport_data->mqttClient);
XinZhangMS 0:f7f1f0d76dd6 2937 }
XinZhangMS 0:f7f1f0d76dd6 2938 }
XinZhangMS 0:f7f1f0d76dd6 2939 }
XinZhangMS 0:f7f1f0d76dd6 2940
XinZhangMS 0:f7f1f0d76dd6 2941 IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_GetSendStatus(IOTHUB_DEVICE_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus)
XinZhangMS 0:f7f1f0d76dd6 2942 {
XinZhangMS 0:f7f1f0d76dd6 2943 IOTHUB_CLIENT_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 2944
XinZhangMS 0:f7f1f0d76dd6 2945 if (handle == NULL || iotHubClientStatus == NULL)
XinZhangMS 0:f7f1f0d76dd6 2946 {
XinZhangMS 0:f7f1f0d76dd6 2947 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */
XinZhangMS 0:f7f1f0d76dd6 2948 LogError("invalid arument.");
XinZhangMS 0:f7f1f0d76dd6 2949 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2950 }
XinZhangMS 0:f7f1f0d76dd6 2951 else
XinZhangMS 0:f7f1f0d76dd6 2952 {
XinZhangMS 0:f7f1f0d76dd6 2953 MQTTTRANSPORT_HANDLE_DATA* handleData = (MQTTTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 2954 if (!DList_IsListEmpty(handleData->waitingToSend) || !DList_IsListEmpty(&(handleData->telemetry_waitingForAck)))
XinZhangMS 0:f7f1f0d76dd6 2955 {
XinZhangMS 0:f7f1f0d76dd6 2956 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */
XinZhangMS 0:f7f1f0d76dd6 2957 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY;
XinZhangMS 0:f7f1f0d76dd6 2958 }
XinZhangMS 0:f7f1f0d76dd6 2959 else
XinZhangMS 0:f7f1f0d76dd6 2960 {
XinZhangMS 0:f7f1f0d76dd6 2961 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransport_MQTT_Common_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */
XinZhangMS 0:f7f1f0d76dd6 2962 *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE;
XinZhangMS 0:f7f1f0d76dd6 2963 }
XinZhangMS 0:f7f1f0d76dd6 2964 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 2965 }
XinZhangMS 0:f7f1f0d76dd6 2966 return result;
XinZhangMS 0:f7f1f0d76dd6 2967 }
XinZhangMS 0:f7f1f0d76dd6 2968
XinZhangMS 0:f7f1f0d76dd6 2969 IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_SetOption(TRANSPORT_LL_HANDLE handle, const char* option, const void* value)
XinZhangMS 0:f7f1f0d76dd6 2970 {
XinZhangMS 0:f7f1f0d76dd6 2971 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_021: [If any parameter is NULL then IoTHubTransport_MQTT_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG.] */
XinZhangMS 0:f7f1f0d76dd6 2972 IOTHUB_CLIENT_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 2973 if (
XinZhangMS 0:f7f1f0d76dd6 2974 (handle == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 2975 (option == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 2976 (value == NULL)
XinZhangMS 0:f7f1f0d76dd6 2977 )
XinZhangMS 0:f7f1f0d76dd6 2978 {
XinZhangMS 0:f7f1f0d76dd6 2979 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 2980 LogError("invalid parameter (NULL) passed to IoTHubTransport_MQTT_Common_SetOption.");
XinZhangMS 0:f7f1f0d76dd6 2981 }
XinZhangMS 0:f7f1f0d76dd6 2982 else
XinZhangMS 0:f7f1f0d76dd6 2983 {
XinZhangMS 0:f7f1f0d76dd6 2984 MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 2985
XinZhangMS 0:f7f1f0d76dd6 2986 IOTHUB_CREDENTIAL_TYPE cred_type = IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module);
XinZhangMS 0:f7f1f0d76dd6 2987
XinZhangMS 0:f7f1f0d76dd6 2988 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_031: [If the option parameter is set to "logtrace" then the value shall be a bool_ptr and the value will determine if the mqtt client log is on or off.] */
XinZhangMS 0:f7f1f0d76dd6 2989 if (strcmp(OPTION_LOG_TRACE, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 2990 {
XinZhangMS 0:f7f1f0d76dd6 2991 transport_data->log_trace = *((bool*)value);
XinZhangMS 0:f7f1f0d76dd6 2992 mqtt_client_set_trace(transport_data->mqttClient, transport_data->log_trace, transport_data->raw_trace);
XinZhangMS 0:f7f1f0d76dd6 2993 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 2994 }
XinZhangMS 0:f7f1f0d76dd6 2995 else if (strcmp("rawlogtrace", option) == 0)
XinZhangMS 0:f7f1f0d76dd6 2996 {
XinZhangMS 0:f7f1f0d76dd6 2997 transport_data->raw_trace = *((bool*)value);
XinZhangMS 0:f7f1f0d76dd6 2998 mqtt_client_set_trace(transport_data->mqttClient, transport_data->log_trace, transport_data->raw_trace);
XinZhangMS 0:f7f1f0d76dd6 2999 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3000 }
XinZhangMS 0:f7f1f0d76dd6 3001 else if (strcmp(OPTION_AUTO_URL_ENCODE_DECODE, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 3002 {
XinZhangMS 0:f7f1f0d76dd6 3003 transport_data->auto_url_encode_decode = *((bool*)value);
XinZhangMS 0:f7f1f0d76dd6 3004 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3005 }
XinZhangMS 0:f7f1f0d76dd6 3006 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_07_052: [ If the option parameter is set to "sas_token_lifetime" then the value shall be a size_t_ptr and the value will determine the mqtt sas token lifetime.] */
XinZhangMS 0:f7f1f0d76dd6 3007 else if (strcmp(OPTION_SAS_TOKEN_LIFETIME, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 3008 {
XinZhangMS 0:f7f1f0d76dd6 3009 size_t* sas_lifetime = (size_t*)value;
XinZhangMS 0:f7f1f0d76dd6 3010 transport_data->option_sas_token_lifetime_secs = *sas_lifetime;
XinZhangMS 0:f7f1f0d76dd6 3011 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3012 }
XinZhangMS 0:f7f1f0d76dd6 3013 else if (strcmp(OPTION_CONNECTION_TIMEOUT, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 3014 {
XinZhangMS 0:f7f1f0d76dd6 3015 int* connection_time = (int*)value;
XinZhangMS 0:f7f1f0d76dd6 3016 if (*connection_time != transport_data->connect_timeout_in_sec)
XinZhangMS 0:f7f1f0d76dd6 3017 {
XinZhangMS 0:f7f1f0d76dd6 3018 transport_data->connect_timeout_in_sec = (uint16_t)(*connection_time);
XinZhangMS 0:f7f1f0d76dd6 3019 }
XinZhangMS 0:f7f1f0d76dd6 3020 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3021 }
XinZhangMS 0:f7f1f0d76dd6 3022 else if (strcmp(OPTION_KEEP_ALIVE, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 3023 {
XinZhangMS 0:f7f1f0d76dd6 3024 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_036: [If the option parameter is set to "keepalive" then the value shall be a int_ptr and the value will determine the mqtt keepalive time that is set for pings.] */
XinZhangMS 0:f7f1f0d76dd6 3025 int* keepAliveOption = (int*)value;
XinZhangMS 0:f7f1f0d76dd6 3026 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_037 : [If the option parameter is set to supplied int_ptr keepalive is the same value as the existing keepalive then IoTHubTransport_MQTT_Common_SetOption shall do nothing.] */
XinZhangMS 0:f7f1f0d76dd6 3027 if (*keepAliveOption != transport_data->keepAliveValue)
XinZhangMS 0:f7f1f0d76dd6 3028 {
XinZhangMS 0:f7f1f0d76dd6 3029 transport_data->keepAliveValue = (uint16_t)(*keepAliveOption);
XinZhangMS 0:f7f1f0d76dd6 3030 if (transport_data->mqttClientStatus != MQTT_CLIENT_STATUS_NOT_CONNECTED)
XinZhangMS 0:f7f1f0d76dd6 3031 {
XinZhangMS 0:f7f1f0d76dd6 3032 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_038: [If the client is connected when the keepalive is set then IoTHubTransport_MQTT_Common_SetOption shall disconnect and reconnect with the specified keepalive value.] */
XinZhangMS 0:f7f1f0d76dd6 3033 DisconnectFromClient(transport_data);
XinZhangMS 0:f7f1f0d76dd6 3034 }
XinZhangMS 0:f7f1f0d76dd6 3035 }
XinZhangMS 0:f7f1f0d76dd6 3036 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3037 }
XinZhangMS 0:f7f1f0d76dd6 3038 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 3039 else if ((strcmp(OPTION_X509_CERT, option) == 0) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509 && cred_type != IOTHUB_CREDENTIAL_TYPE_UNKNOWN))
XinZhangMS 0:f7f1f0d76dd6 3040 {
XinZhangMS 0:f7f1f0d76dd6 3041 LogError("x509certificate specified, but authentication method is not x509");
XinZhangMS 0:f7f1f0d76dd6 3042 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 3043 }
XinZhangMS 0:f7f1f0d76dd6 3044 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_040: [If the option parameter is set to "x509privatekey" then the value shall be a const char of the RSA Private Key to be used for x509.] */
XinZhangMS 0:f7f1f0d76dd6 3045 else if ((strcmp(OPTION_X509_PRIVATE_KEY, option) == 0) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509 && cred_type != IOTHUB_CREDENTIAL_TYPE_UNKNOWN))
XinZhangMS 0:f7f1f0d76dd6 3046 {
XinZhangMS 0:f7f1f0d76dd6 3047 LogError("x509privatekey specified, but authentication method is not x509");
XinZhangMS 0:f7f1f0d76dd6 3048 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 3049 }
XinZhangMS 0:f7f1f0d76dd6 3050 else if (strcmp(OPTION_HTTP_PROXY, option) == 0)
XinZhangMS 0:f7f1f0d76dd6 3051 {
XinZhangMS 0:f7f1f0d76dd6 3052 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_001: [ If `option` is `proxy_data`, `value` shall be used as an `HTTP_PROXY_OPTIONS*`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3053 HTTP_PROXY_OPTIONS* proxy_options = (HTTP_PROXY_OPTIONS*)value;
XinZhangMS 0:f7f1f0d76dd6 3054
XinZhangMS 0:f7f1f0d76dd6 3055 if (transport_data->xioTransport != NULL)
XinZhangMS 0:f7f1f0d76dd6 3056 {
XinZhangMS 0:f7f1f0d76dd6 3057 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_007: [ If the underlying IO has already been created, then `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3058 LogError("Cannot set proxy option once the underlying IO is created");
XinZhangMS 0:f7f1f0d76dd6 3059 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3060 }
XinZhangMS 0:f7f1f0d76dd6 3061 else if (proxy_options->host_address == NULL)
XinZhangMS 0:f7f1f0d76dd6 3062 {
XinZhangMS 0:f7f1f0d76dd6 3063 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_003: [ If `host_address` is NULL, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3064 LogError("NULL host_address in proxy options");
XinZhangMS 0:f7f1f0d76dd6 3065 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 3066 }
XinZhangMS 0:f7f1f0d76dd6 3067 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_006: [ If only one of `username` and `password` is NULL, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_INVALID_ARG`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3068 else if (((proxy_options->username == NULL) || (proxy_options->password == NULL)) &&
XinZhangMS 0:f7f1f0d76dd6 3069 (proxy_options->username != proxy_options->password))
XinZhangMS 0:f7f1f0d76dd6 3070 {
XinZhangMS 0:f7f1f0d76dd6 3071 LogError("Only one of username and password for proxy settings was NULL");
XinZhangMS 0:f7f1f0d76dd6 3072 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 3073 }
XinZhangMS 0:f7f1f0d76dd6 3074 else
XinZhangMS 0:f7f1f0d76dd6 3075 {
XinZhangMS 0:f7f1f0d76dd6 3076 char* copied_proxy_hostname = NULL;
XinZhangMS 0:f7f1f0d76dd6 3077 char* copied_proxy_username = NULL;
XinZhangMS 0:f7f1f0d76dd6 3078 char* copied_proxy_password = NULL;
XinZhangMS 0:f7f1f0d76dd6 3079
XinZhangMS 0:f7f1f0d76dd6 3080 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_002: [ The fields `host_address`, `port`, `username` and `password` shall be saved for later used (needed when creating the underlying IO to be used by the transport). ]*/
XinZhangMS 0:f7f1f0d76dd6 3081 transport_data->http_proxy_port = proxy_options->port;
XinZhangMS 0:f7f1f0d76dd6 3082 if (mallocAndStrcpy_s(&copied_proxy_hostname, proxy_options->host_address) != 0)
XinZhangMS 0:f7f1f0d76dd6 3083 {
XinZhangMS 0:f7f1f0d76dd6 3084 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_004: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3085 LogError("Cannot copy HTTP proxy hostname");
XinZhangMS 0:f7f1f0d76dd6 3086 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3087 }
XinZhangMS 0:f7f1f0d76dd6 3088 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_005: [ `username` and `password` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 3089 else if ((proxy_options->username != NULL) && (mallocAndStrcpy_s(&copied_proxy_username, proxy_options->username) != 0))
XinZhangMS 0:f7f1f0d76dd6 3090 {
XinZhangMS 0:f7f1f0d76dd6 3091 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_004: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3092 free(copied_proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 3093 LogError("Cannot copy HTTP proxy username");
XinZhangMS 0:f7f1f0d76dd6 3094 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3095 }
XinZhangMS 0:f7f1f0d76dd6 3096 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_005: [ `username` and `password` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 3097 else if ((proxy_options->password != NULL) && (mallocAndStrcpy_s(&copied_proxy_password, proxy_options->password) != 0))
XinZhangMS 0:f7f1f0d76dd6 3098 {
XinZhangMS 0:f7f1f0d76dd6 3099 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_004: [ If copying `host_address`, `username` or `password` fails, `IoTHubTransport_MQTT_Common_SetOption` shall fail and return `IOTHUB_CLIENT_ERROR`. ]*/
XinZhangMS 0:f7f1f0d76dd6 3100 if (copied_proxy_username != NULL)
XinZhangMS 0:f7f1f0d76dd6 3101 {
XinZhangMS 0:f7f1f0d76dd6 3102 free(copied_proxy_username);
XinZhangMS 0:f7f1f0d76dd6 3103 }
XinZhangMS 0:f7f1f0d76dd6 3104 free(copied_proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 3105 LogError("Cannot copy HTTP proxy password");
XinZhangMS 0:f7f1f0d76dd6 3106 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3107 }
XinZhangMS 0:f7f1f0d76dd6 3108 else
XinZhangMS 0:f7f1f0d76dd6 3109 {
XinZhangMS 0:f7f1f0d76dd6 3110 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_009: [ When setting the proxy options succeeds any previously saved proxy options shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 3111 free_proxy_data(transport_data);
XinZhangMS 0:f7f1f0d76dd6 3112
XinZhangMS 0:f7f1f0d76dd6 3113 transport_data->http_proxy_hostname = copied_proxy_hostname;
XinZhangMS 0:f7f1f0d76dd6 3114 transport_data->http_proxy_username = copied_proxy_username;
XinZhangMS 0:f7f1f0d76dd6 3115 transport_data->http_proxy_password = copied_proxy_password;
XinZhangMS 0:f7f1f0d76dd6 3116
XinZhangMS 0:f7f1f0d76dd6 3117 /* Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_01_008: [ If setting the `proxy_data` option suceeds, `IoTHubTransport_MQTT_Common_SetOption` shall return `IOTHUB_CLIENT_OK` ]*/
XinZhangMS 0:f7f1f0d76dd6 3118 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3119 }
XinZhangMS 0:f7f1f0d76dd6 3120 }
XinZhangMS 0:f7f1f0d76dd6 3121 }
XinZhangMS 0:f7f1f0d76dd6 3122 else
XinZhangMS 0:f7f1f0d76dd6 3123 {
XinZhangMS 0:f7f1f0d76dd6 3124 /* 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.] */
XinZhangMS 0:f7f1f0d76dd6 3125 if (((strcmp(OPTION_X509_CERT, option) == 0) || (strcmp(OPTION_X509_PRIVATE_KEY, option) == 0)) && (cred_type != IOTHUB_CREDENTIAL_TYPE_X509))
XinZhangMS 0:f7f1f0d76dd6 3126 {
XinZhangMS 0:f7f1f0d76dd6 3127 IoTHubClient_Auth_Set_x509_Type(transport_data->authorization_module, true);
XinZhangMS 0:f7f1f0d76dd6 3128 }
XinZhangMS 0:f7f1f0d76dd6 3129
XinZhangMS 0:f7f1f0d76dd6 3130 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_032: [IoTHubTransport_MQTT_Common_SetOption shall pass down the option to xio_setoption if the option parameter is not a known option string for the MQTT transport.] */
XinZhangMS 0:f7f1f0d76dd6 3131 if (GetTransportProviderIfNecessary(transport_data) == 0)
XinZhangMS 0:f7f1f0d76dd6 3132 {
XinZhangMS 0:f7f1f0d76dd6 3133 if (xio_setoption(transport_data->xioTransport, option, value) == 0)
XinZhangMS 0:f7f1f0d76dd6 3134 {
XinZhangMS 0:f7f1f0d76dd6 3135 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3136 }
XinZhangMS 0:f7f1f0d76dd6 3137 else
XinZhangMS 0:f7f1f0d76dd6 3138 {
XinZhangMS 0:f7f1f0d76dd6 3139 /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_132: [IoTHubTransport_MQTT_Common_SetOption shall return IOTHUB_CLIENT_INVALID_ARG xio_setoption fails] */
XinZhangMS 0:f7f1f0d76dd6 3140 result = IOTHUB_CLIENT_INVALID_ARG;
XinZhangMS 0:f7f1f0d76dd6 3141 }
XinZhangMS 0:f7f1f0d76dd6 3142 }
XinZhangMS 0:f7f1f0d76dd6 3143 else
XinZhangMS 0:f7f1f0d76dd6 3144 {
XinZhangMS 0:f7f1f0d76dd6 3145 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3146 }
XinZhangMS 0:f7f1f0d76dd6 3147 }
XinZhangMS 0:f7f1f0d76dd6 3148 }
XinZhangMS 0:f7f1f0d76dd6 3149 return result;
XinZhangMS 0:f7f1f0d76dd6 3150 }
XinZhangMS 0:f7f1f0d76dd6 3151
XinZhangMS 0:f7f1f0d76dd6 3152 static bool check_module_ids_equal(const char* transportModuleId, const char* deviceModuleId)
XinZhangMS 0:f7f1f0d76dd6 3153 {
XinZhangMS 0:f7f1f0d76dd6 3154 if ((transportModuleId != NULL) && (deviceModuleId == NULL))
XinZhangMS 0:f7f1f0d76dd6 3155 {
XinZhangMS 0:f7f1f0d76dd6 3156 return false;
XinZhangMS 0:f7f1f0d76dd6 3157 }
XinZhangMS 0:f7f1f0d76dd6 3158 else if ((transportModuleId == NULL) && (deviceModuleId != NULL))
XinZhangMS 0:f7f1f0d76dd6 3159 {
XinZhangMS 0:f7f1f0d76dd6 3160 return false;
XinZhangMS 0:f7f1f0d76dd6 3161 }
XinZhangMS 0:f7f1f0d76dd6 3162 else if ((transportModuleId == NULL) && (deviceModuleId == NULL))
XinZhangMS 0:f7f1f0d76dd6 3163 {
XinZhangMS 0:f7f1f0d76dd6 3164 return true;
XinZhangMS 0:f7f1f0d76dd6 3165 }
XinZhangMS 0:f7f1f0d76dd6 3166 else
XinZhangMS 0:f7f1f0d76dd6 3167 {
XinZhangMS 0:f7f1f0d76dd6 3168 return (0 == strcmp(transportModuleId, deviceModuleId));
XinZhangMS 0:f7f1f0d76dd6 3169 }
XinZhangMS 0:f7f1f0d76dd6 3170 }
XinZhangMS 0:f7f1f0d76dd6 3171
XinZhangMS 0:f7f1f0d76dd6 3172 IOTHUB_DEVICE_HANDLE IoTHubTransport_MQTT_Common_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, PDLIST_ENTRY waitingToSend)
XinZhangMS 0:f7f1f0d76dd6 3173 {
XinZhangMS 0:f7f1f0d76dd6 3174 IOTHUB_DEVICE_HANDLE result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3175 (void)iotHubClientHandle;
XinZhangMS 0:f7f1f0d76dd6 3176
XinZhangMS 0:f7f1f0d76dd6 3177 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_001: [ IoTHubTransport_MQTT_Common_Register shall return NULL if the TRANSPORT_LL_HANDLE is NULL.]
XinZhangMS 0:f7f1f0d76dd6 3178 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_002: [ IoTHubTransport_MQTT_Common_Register shall return NULL if device or waitingToSend are NULL.]
XinZhangMS 0:f7f1f0d76dd6 3179 if ((handle == NULL) || (device == NULL) || (waitingToSend == NULL))
XinZhangMS 0:f7f1f0d76dd6 3180 {
XinZhangMS 0:f7f1f0d76dd6 3181 LogError("IoTHubTransport_MQTT_Common_Register: handle, device or waitingToSend is NULL.");
XinZhangMS 0:f7f1f0d76dd6 3182 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3183 }
XinZhangMS 0:f7f1f0d76dd6 3184 else
XinZhangMS 0:f7f1f0d76dd6 3185 {
XinZhangMS 0:f7f1f0d76dd6 3186 MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)handle;
XinZhangMS 0:f7f1f0d76dd6 3187
XinZhangMS 0:f7f1f0d76dd6 3188 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_001: [ IoTHubTransport_MQTT_Common_Register shall return NULL if deviceId, or both deviceKey and deviceSasToken are NULL.]
XinZhangMS 0:f7f1f0d76dd6 3189 if (device->deviceId == NULL)
XinZhangMS 0:f7f1f0d76dd6 3190 {
XinZhangMS 0:f7f1f0d76dd6 3191 LogError("IoTHubTransport_MQTT_Common_Register: deviceId is NULL.");
XinZhangMS 0:f7f1f0d76dd6 3192 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3193 }
XinZhangMS 0:f7f1f0d76dd6 3194 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_03_002: [ IoTHubTransport_MQTT_Common_Register shall return NULL if both deviceKey and deviceSasToken are provided.]
XinZhangMS 0:f7f1f0d76dd6 3195 else if ((device->deviceKey != NULL) && (device->deviceSasToken != NULL))
XinZhangMS 0:f7f1f0d76dd6 3196 {
XinZhangMS 0:f7f1f0d76dd6 3197 LogError("IoTHubTransport_MQTT_Common_Register: Both deviceKey and deviceSasToken are defined. Only one can be used.");
XinZhangMS 0:f7f1f0d76dd6 3198 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3199 }
XinZhangMS 0:f7f1f0d76dd6 3200 else
XinZhangMS 0:f7f1f0d76dd6 3201 {
XinZhangMS 0:f7f1f0d76dd6 3202 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_003: [ IoTHubTransport_MQTT_Common_Register shall return NULL if deviceId or deviceKey do not match the deviceId and deviceKey passed in during IoTHubTransport_MQTT_Common_Create.]
XinZhangMS 0:f7f1f0d76dd6 3203 if (strcmp(STRING_c_str(transport_data->device_id), device->deviceId) != 0)
XinZhangMS 0:f7f1f0d76dd6 3204 {
XinZhangMS 0:f7f1f0d76dd6 3205 LogError("IoTHubTransport_MQTT_Common_Register: deviceId does not match.");
XinZhangMS 0:f7f1f0d76dd6 3206 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3207 }
XinZhangMS 0:f7f1f0d76dd6 3208 else if (!check_module_ids_equal(STRING_c_str(transport_data->module_id), device->moduleId))
XinZhangMS 0:f7f1f0d76dd6 3209 {
XinZhangMS 0:f7f1f0d76dd6 3210 LogError("IoTHubTransport_MQTT_Common_Register: moduleId does not match.");
XinZhangMS 0:f7f1f0d76dd6 3211 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3212 }
XinZhangMS 0:f7f1f0d76dd6 3213 else if (IoTHubClient_Auth_Get_Credential_Type(transport_data->authorization_module) == IOTHUB_CREDENTIAL_TYPE_DEVICE_KEY &&
XinZhangMS 0:f7f1f0d76dd6 3214 (strcmp(IoTHubClient_Auth_Get_DeviceKey(transport_data->authorization_module), device->deviceKey) != 0))
XinZhangMS 0:f7f1f0d76dd6 3215 {
XinZhangMS 0:f7f1f0d76dd6 3216 LogError("IoTHubTransport_MQTT_Common_Register: deviceKey does not match.");
XinZhangMS 0:f7f1f0d76dd6 3217 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3218 }
XinZhangMS 0:f7f1f0d76dd6 3219 else
XinZhangMS 0:f7f1f0d76dd6 3220 {
XinZhangMS 0:f7f1f0d76dd6 3221 if (transport_data->isRegistered == true)
XinZhangMS 0:f7f1f0d76dd6 3222 {
XinZhangMS 0:f7f1f0d76dd6 3223 LogError("Transport already has device registered by id: [%s]", device->deviceId);
XinZhangMS 0:f7f1f0d76dd6 3224 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3225 }
XinZhangMS 0:f7f1f0d76dd6 3226 else
XinZhangMS 0:f7f1f0d76dd6 3227 {
XinZhangMS 0:f7f1f0d76dd6 3228 transport_data->isRegistered = true;
XinZhangMS 0:f7f1f0d76dd6 3229 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_004: [ IoTHubTransport_MQTT_Common_Register shall return the TRANSPORT_LL_HANDLE as the IOTHUB_DEVICE_HANDLE. ]
XinZhangMS 0:f7f1f0d76dd6 3230 result = (IOTHUB_DEVICE_HANDLE)handle;
XinZhangMS 0:f7f1f0d76dd6 3231 }
XinZhangMS 0:f7f1f0d76dd6 3232 }
XinZhangMS 0:f7f1f0d76dd6 3233 }
XinZhangMS 0:f7f1f0d76dd6 3234 }
XinZhangMS 0:f7f1f0d76dd6 3235
XinZhangMS 0:f7f1f0d76dd6 3236 return result;
XinZhangMS 0:f7f1f0d76dd6 3237 }
XinZhangMS 0:f7f1f0d76dd6 3238
XinZhangMS 0:f7f1f0d76dd6 3239 void IoTHubTransport_MQTT_Common_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle)
XinZhangMS 0:f7f1f0d76dd6 3240 {
XinZhangMS 0:f7f1f0d76dd6 3241 // Codes_SRS_IOTHUB_MQTT_TRANSPORT_17_005: [ If deviceHandle is NULL `IoTHubTransport_MQTT_Common_Unregister` shall do nothing. ]
XinZhangMS 0:f7f1f0d76dd6 3242 if (deviceHandle != NULL)
XinZhangMS 0:f7f1f0d76dd6 3243 {
XinZhangMS 0:f7f1f0d76dd6 3244 MQTTTRANSPORT_HANDLE_DATA* transport_data = (MQTTTRANSPORT_HANDLE_DATA*)deviceHandle;
XinZhangMS 0:f7f1f0d76dd6 3245
XinZhangMS 0:f7f1f0d76dd6 3246 transport_data->isRegistered = false;
XinZhangMS 0:f7f1f0d76dd6 3247 }
XinZhangMS 0:f7f1f0d76dd6 3248 }
XinZhangMS 0:f7f1f0d76dd6 3249
XinZhangMS 0:f7f1f0d76dd6 3250 STRING_HANDLE IoTHubTransport_MQTT_Common_GetHostname(TRANSPORT_LL_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 3251 {
XinZhangMS 0:f7f1f0d76dd6 3252 STRING_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 3253 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_02_001: [ If handle is NULL then IoTHubTransport_MQTT_Common_GetHostname shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 3254 if (handle == NULL)
XinZhangMS 0:f7f1f0d76dd6 3255 {
XinZhangMS 0:f7f1f0d76dd6 3256 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 3257 }
XinZhangMS 0:f7f1f0d76dd6 3258 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_02_002: [ Otherwise IoTHubTransport_MQTT_Common_GetHostname shall return a non-NULL STRING_HANDLE containg the hostname. ]*/
XinZhangMS 0:f7f1f0d76dd6 3259 else if ((result = STRING_clone(((MQTTTRANSPORT_HANDLE_DATA*)(handle))->hostAddress)) == NULL)
XinZhangMS 0:f7f1f0d76dd6 3260 {
XinZhangMS 0:f7f1f0d76dd6 3261 LogError("Cannot provide the target host name (STRING_clone failed).");
XinZhangMS 0:f7f1f0d76dd6 3262 }
XinZhangMS 0:f7f1f0d76dd6 3263
XinZhangMS 0:f7f1f0d76dd6 3264 return result;
XinZhangMS 0:f7f1f0d76dd6 3265 }
XinZhangMS 0:f7f1f0d76dd6 3266
XinZhangMS 0:f7f1f0d76dd6 3267 IOTHUB_CLIENT_RESULT IoTHubTransport_MQTT_Common_SendMessageDisposition(MESSAGE_CALLBACK_INFO* message_data, IOTHUBMESSAGE_DISPOSITION_RESULT disposition)
XinZhangMS 0:f7f1f0d76dd6 3268 {
XinZhangMS 0:f7f1f0d76dd6 3269 (void)disposition;
XinZhangMS 0:f7f1f0d76dd6 3270
XinZhangMS 0:f7f1f0d76dd6 3271 IOTHUB_CLIENT_RESULT result;
XinZhangMS 0:f7f1f0d76dd6 3272 if (message_data)
XinZhangMS 0:f7f1f0d76dd6 3273 {
XinZhangMS 0:f7f1f0d76dd6 3274 if (message_data->messageHandle)
XinZhangMS 0:f7f1f0d76dd6 3275 {
XinZhangMS 0:f7f1f0d76dd6 3276 IoTHubMessage_Destroy(message_data->messageHandle);
XinZhangMS 0:f7f1f0d76dd6 3277 result = IOTHUB_CLIENT_OK;
XinZhangMS 0:f7f1f0d76dd6 3278 }
XinZhangMS 0:f7f1f0d76dd6 3279 else
XinZhangMS 0:f7f1f0d76dd6 3280 {
XinZhangMS 0:f7f1f0d76dd6 3281 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_10_002: [If any of the messageData fields are NULL, IoTHubTransport_MQTT_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 3282 LogError("message handle is NULL");
XinZhangMS 0:f7f1f0d76dd6 3283 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3284 }
XinZhangMS 0:f7f1f0d76dd6 3285 free(message_data);
XinZhangMS 0:f7f1f0d76dd6 3286 }
XinZhangMS 0:f7f1f0d76dd6 3287 else
XinZhangMS 0:f7f1f0d76dd6 3288 {
XinZhangMS 0:f7f1f0d76dd6 3289 /*Codes_SRS_IOTHUB_MQTT_TRANSPORT_10_001: [If messageData is NULL, IoTHubTransport_MQTT_Common_SendMessageDisposition shall fail and return IOTHUB_CLIENT_ERROR. ]*/
XinZhangMS 0:f7f1f0d76dd6 3290 LogError("message_data is NULL");
XinZhangMS 0:f7f1f0d76dd6 3291 result = IOTHUB_CLIENT_ERROR;
XinZhangMS 0:f7f1f0d76dd6 3292 }
XinZhangMS 0:f7f1f0d76dd6 3293 return result;
XinZhangMS 0:f7f1f0d76dd6 3294 }
XinZhangMS 0:f7f1f0d76dd6 3295
XinZhangMS 0:f7f1f0d76dd6 3296
XinZhangMS 0:f7f1f0d76dd6 3297 int IoTHubTransport_MQTT_Common_Subscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 3298 {
XinZhangMS 0:f7f1f0d76dd6 3299 int result;
XinZhangMS 0:f7f1f0d76dd6 3300 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 3301 if (transport_data == NULL)
XinZhangMS 0:f7f1f0d76dd6 3302 {
XinZhangMS 0:f7f1f0d76dd6 3303 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_066: [ If parameter handle is NULL than IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall return a non-zero value.]
XinZhangMS 0:f7f1f0d76dd6 3304 LogError("Invalid handle parameter. NULL.");
XinZhangMS 0:f7f1f0d76dd6 3305 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 3306 }
XinZhangMS 0:f7f1f0d76dd6 3307 else if (transport_data->module_id == NULL)
XinZhangMS 0:f7f1f0d76dd6 3308 {
XinZhangMS 0:f7f1f0d76dd6 3309 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_073: [ If module ID is not set on the transpont, IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue shall fail.]
XinZhangMS 0:f7f1f0d76dd6 3310 LogError("ModuleID must be specified for input queues. NULL.");
XinZhangMS 0:f7f1f0d76dd6 3311 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 3312 }
XinZhangMS 0:f7f1f0d76dd6 3313 else if ((transport_data->topic_InputQueue == NULL) &&
XinZhangMS 0:f7f1f0d76dd6 3314 (transport_data->topic_InputQueue = STRING_construct_sprintf(TOPIC_INPUT_QUEUE_NAME, STRING_c_str(transport_data->device_id), STRING_c_str(transport_data->module_id))) == NULL)
XinZhangMS 0:f7f1f0d76dd6 3315 {
XinZhangMS 0:f7f1f0d76dd6 3316 LogError("Failure constructing Message Topic");
XinZhangMS 0:f7f1f0d76dd6 3317 result = __FAILURE__;
XinZhangMS 0:f7f1f0d76dd6 3318 }
XinZhangMS 0:f7f1f0d76dd6 3319 else
XinZhangMS 0:f7f1f0d76dd6 3320 {
XinZhangMS 0:f7f1f0d76dd6 3321 // 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.]
XinZhangMS 0:f7f1f0d76dd6 3322 transport_data->topics_ToSubscribe |= SUBSCRIBE_INPUT_QUEUE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 3323 changeStateToSubscribeIfAllowed(transport_data);
XinZhangMS 0:f7f1f0d76dd6 3324 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_070: [ On success IoTHubTransport_MQTT_Common_Subscribe_InputQueue shall return 0.]
XinZhangMS 0:f7f1f0d76dd6 3325 result = 0;
XinZhangMS 0:f7f1f0d76dd6 3326 }
XinZhangMS 0:f7f1f0d76dd6 3327 return result;
XinZhangMS 0:f7f1f0d76dd6 3328 }
XinZhangMS 0:f7f1f0d76dd6 3329
XinZhangMS 0:f7f1f0d76dd6 3330 void IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue(IOTHUB_DEVICE_HANDLE handle)
XinZhangMS 0:f7f1f0d76dd6 3331 {
XinZhangMS 0:f7f1f0d76dd6 3332 PMQTTTRANSPORT_HANDLE_DATA transport_data = (PMQTTTRANSPORT_HANDLE_DATA)handle;
XinZhangMS 0:f7f1f0d76dd6 3333 if ((transport_data != NULL) && (transport_data->topic_InputQueue != NULL))
XinZhangMS 0:f7f1f0d76dd6 3334 {
XinZhangMS 0:f7f1f0d76dd6 3335 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_072: [ IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue shall call mqtt_client_unsubscribe to unsubscribe the mqtt input queue message topic.]
XinZhangMS 0:f7f1f0d76dd6 3336 const char* unsubscribe[1];
XinZhangMS 0:f7f1f0d76dd6 3337 unsubscribe[0] = STRING_c_str(transport_data->topic_InputQueue);
XinZhangMS 0:f7f1f0d76dd6 3338 if (mqtt_client_unsubscribe(transport_data->mqttClient, get_next_packet_id(transport_data), unsubscribe, 1) != 0)
XinZhangMS 0:f7f1f0d76dd6 3339 {
XinZhangMS 0:f7f1f0d76dd6 3340 LogError("Failure calling mqtt_client_unsubscribe");
XinZhangMS 0:f7f1f0d76dd6 3341 }
XinZhangMS 0:f7f1f0d76dd6 3342 STRING_delete(transport_data->topic_InputQueue);
XinZhangMS 0:f7f1f0d76dd6 3343 transport_data->topic_InputQueue = NULL;
XinZhangMS 0:f7f1f0d76dd6 3344 transport_data->topics_ToSubscribe &= ~SUBSCRIBE_INPUT_QUEUE_TOPIC;
XinZhangMS 0:f7f1f0d76dd6 3345 }
XinZhangMS 0:f7f1f0d76dd6 3346 else
XinZhangMS 0:f7f1f0d76dd6 3347 {
XinZhangMS 0:f7f1f0d76dd6 3348 // Codes_SRS_IOTHUB_TRANSPORT_MQTT_COMMON_31_071: [ If parameter handle is NULL then IoTHubTransport_MQTT_Common_Unsubscribe_InputQueue shall do nothing.]
XinZhangMS 0:f7f1f0d76dd6 3349 LogError("Invalid argument to unsubscribe input queue (NULL).");
XinZhangMS 0:f7f1f0d76dd6 3350 }
XinZhangMS 0:f7f1f0d76dd6 3351 }
XinZhangMS 0:f7f1f0d76dd6 3352
XinZhangMS 0:f7f1f0d76dd6 3353