A small footprint MQTT library

Dependents:   STM32F746_iothub_client_sample_mqtt FXOS8700CQ_To_Azure_IoT f767zi_mqtt FXOS8700CQ_To_Azure_IoT ... more

Committer:
AzureIoTClient
Date:
Thu Oct 04 09:16:34 2018 -0700
Revision:
30:712bcbf21afa
Parent:
29:7bb0aae34648
1.2.10

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Azure.IoT Build 0:ef4901974abc 1 // Copyright (c) Microsoft. All rights reserved.
Azure.IoT Build 0:ef4901974abc 2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
Azure.IoT Build 0:ef4901974abc 3
Azure.IoT Build 0:ef4901974abc 4 #include <stdlib.h>
AzureIoTClient 15:ec5a36121959 5 #include "azure_c_shared_utility/optimize_size.h"
Azure.IoT Build 0:ef4901974abc 6 #include "azure_c_shared_utility/gballoc.h"
Azure.IoT Build 0:ef4901974abc 7 #include "azure_c_shared_utility/platform.h"
Azure.IoT Build 0:ef4901974abc 8 #include "azure_c_shared_utility/tickcounter.h"
Azure.IoT Build 0:ef4901974abc 9 #include "azure_c_shared_utility/crt_abstractions.h"
Azure.IoT Build 4:e7167dabd6e4 10 #include "azure_c_shared_utility/xlogging.h"
AzureIoTClient 8:83bb166aba73 11 #include "azure_c_shared_utility/strings.h"
AzureIoTClient 8:83bb166aba73 12 #include "azure_c_shared_utility/agenttime.h"
AzureIoTClient 9:37d14c31ff6e 13 #include "azure_c_shared_utility/threadapi.h"
Azure.IoT Build 0:ef4901974abc 14
Azure.IoT Build 0:ef4901974abc 15 #include "azure_umqtt_c/mqtt_client.h"
Azure.IoT Build 0:ef4901974abc 16 #include "azure_umqtt_c/mqtt_codec.h"
AzureIoTClient 8:83bb166aba73 17 #include <inttypes.h>
Azure.IoT Build 0:ef4901974abc 18
Azure.IoT Build 0:ef4901974abc 19 #define VARIABLE_HEADER_OFFSET 2
Azure.IoT Build 0:ef4901974abc 20 #define RETAIN_FLAG_MASK 0x1
Azure.IoT Build 0:ef4901974abc 21 #define QOS_LEAST_ONCE_FLAG_MASK 0x2
Azure.IoT Build 0:ef4901974abc 22 #define QOS_EXACTLY_ONCE_FLAG_MASK 0x4
Azure.IoT Build 0:ef4901974abc 23 #define DUPLICATE_FLAG_MASK 0x8
Azure.IoT Build 0:ef4901974abc 24 #define CONNECT_PACKET_MASK 0xf0
AzureIoTClient 1:8dba42ff9701 25 #define TIME_MAX_BUFFER 16
AzureIoTClient 8:83bb166aba73 26 #define DEFAULT_MAX_PING_RESPONSE_TIME 80 // % of time to send pings
AzureIoTClient 23:80794cfb3565 27 #define MAX_CLOSE_RETRIES 2
Azure.IoT Build 0:ef4901974abc 28
AzureIoTClient 24:75f5b91d1c6e 29 static const char* const TRUE_CONST = "true";
AzureIoTClient 24:75f5b91d1c6e 30 static const char* const FALSE_CONST = "false";
AzureIoTClient 8:83bb166aba73 31
AzureIoTClient 8:83bb166aba73 32 DEFINE_ENUM_STRINGS(QOS_VALUE, QOS_VALUE_VALUES);
Azure.IoT Build 0:ef4901974abc 33
Azure.IoT Build 0:ef4901974abc 34 typedef struct MQTT_CLIENT_TAG
Azure.IoT Build 0:ef4901974abc 35 {
Azure.IoT Build 0:ef4901974abc 36 XIO_HANDLE xioHandle;
Azure.IoT Build 0:ef4901974abc 37 MQTTCODEC_HANDLE codec_handle;
Azure.IoT Build 0:ef4901974abc 38 CONTROL_PACKET_TYPE packetState;
Azure.IoT Build 0:ef4901974abc 39 TICK_COUNTER_HANDLE packetTickCntr;
Azure.IoT.Build 10:2ab268507775 40 tickcounter_ms_t packetSendTimeMs;
Azure.IoT Build 0:ef4901974abc 41 ON_MQTT_OPERATION_CALLBACK fnOperationCallback;
Azure.IoT Build 0:ef4901974abc 42 ON_MQTT_MESSAGE_RECV_CALLBACK fnMessageRecv;
Azure.IoT Build 0:ef4901974abc 43 void* ctx;
AzureIoTClient 9:37d14c31ff6e 44 ON_MQTT_ERROR_CALLBACK fnOnErrorCallBack;
AzureIoTClient 9:37d14c31ff6e 45 void* errorCBCtx;
AzureIoTClient 19:e283dcf26037 46 ON_MQTT_DISCONNECTED_CALLBACK disconnect_cb;
AzureIoTClient 19:e283dcf26037 47 void* disconnect_ctx;
Azure.IoT Build 0:ef4901974abc 48 QOS_VALUE qosValue;
Azure.IoT Build 0:ef4901974abc 49 uint16_t keepAliveInterval;
Azure.IoT Build 0:ef4901974abc 50 MQTT_CLIENT_OPTIONS mqttOptions;
Azure.IoT Build 0:ef4901974abc 51 bool clientConnected;
Azure.IoT Build 0:ef4901974abc 52 bool socketConnected;
Azure.IoT Build 0:ef4901974abc 53 bool logTrace;
Azure.IoT Build 0:ef4901974abc 54 bool rawBytesTrace;
Azure.IoT.Build 10:2ab268507775 55 tickcounter_ms_t timeSincePing;
AzureIoTClient 3:9b4e7158ca0d 56 uint16_t maxPingRespTime;
Azure.IoT Build 0:ef4901974abc 57 } MQTT_CLIENT;
Azure.IoT Build 0:ef4901974abc 58
AzureIoTClient 9:37d14c31ff6e 59 static void on_connection_closed(void* context)
AzureIoTClient 9:37d14c31ff6e 60 {
AzureIoTClient 19:e283dcf26037 61 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
AzureIoTClient 19:e283dcf26037 62 if (mqtt_client != NULL)
AzureIoTClient 19:e283dcf26037 63 {
AzureIoTClient 19:e283dcf26037 64 mqtt_client->socketConnected = false;
AzureIoTClient 19:e283dcf26037 65 mqtt_client->clientConnected = false;
AzureIoTClient 19:e283dcf26037 66 if (mqtt_client->disconnect_cb)
AzureIoTClient 19:e283dcf26037 67 {
AzureIoTClient 19:e283dcf26037 68 mqtt_client->disconnect_cb(mqtt_client->disconnect_ctx);
AzureIoTClient 19:e283dcf26037 69 }
AzureIoTClient 19:e283dcf26037 70 }
AzureIoTClient 9:37d14c31ff6e 71 }
AzureIoTClient 9:37d14c31ff6e 72
AzureIoTClient 9:37d14c31ff6e 73 static void close_connection(MQTT_CLIENT* mqtt_client)
AzureIoTClient 9:37d14c31ff6e 74 {
AzureIoTClient 23:80794cfb3565 75 if (mqtt_client->socketConnected)
AzureIoTClient 9:37d14c31ff6e 76 {
AzureIoTClient 23:80794cfb3565 77 (void)xio_close(mqtt_client->xioHandle, on_connection_closed, mqtt_client);
AzureIoTClient 23:80794cfb3565 78 if (mqtt_client->disconnect_cb == NULL)
AzureIoTClient 19:e283dcf26037 79 {
AzureIoTClient 23:80794cfb3565 80 size_t counter = 0;
AzureIoTClient 23:80794cfb3565 81 do
AzureIoTClient 23:80794cfb3565 82 {
AzureIoTClient 23:80794cfb3565 83 xio_dowork(mqtt_client->xioHandle);
AzureIoTClient 23:80794cfb3565 84 counter++;
AzureIoTClient 23:80794cfb3565 85 ThreadAPI_Sleep(2);
AzureIoTClient 23:80794cfb3565 86 } while (mqtt_client->clientConnected && counter < MAX_CLOSE_RETRIES);
AzureIoTClient 23:80794cfb3565 87 }
AzureIoTClient 23:80794cfb3565 88 }
AzureIoTClient 23:80794cfb3565 89 else
AzureIoTClient 23:80794cfb3565 90 {
AzureIoTClient 23:80794cfb3565 91 if (mqtt_client->disconnect_cb)
AzureIoTClient 23:80794cfb3565 92 {
AzureIoTClient 23:80794cfb3565 93 mqtt_client->disconnect_cb(mqtt_client->disconnect_ctx);
AzureIoTClient 23:80794cfb3565 94 }
AzureIoTClient 19:e283dcf26037 95 }
AzureIoTClient 27:a2eb9cb1e731 96 mqtt_client->xioHandle = NULL;
AzureIoTClient 9:37d14c31ff6e 97 }
AzureIoTClient 9:37d14c31ff6e 98
AzureIoTClient 9:37d14c31ff6e 99 static void set_error_callback(MQTT_CLIENT* mqtt_client, MQTT_CLIENT_EVENT_ERROR error_type)
AzureIoTClient 9:37d14c31ff6e 100 {
AzureIoTClient 9:37d14c31ff6e 101 if (mqtt_client->fnOnErrorCallBack)
AzureIoTClient 9:37d14c31ff6e 102 {
AzureIoTClient 9:37d14c31ff6e 103 mqtt_client->fnOnErrorCallBack(mqtt_client, error_type, mqtt_client->errorCBCtx);
AzureIoTClient 9:37d14c31ff6e 104 }
AzureIoTClient 9:37d14c31ff6e 105 close_connection(mqtt_client);
AzureIoTClient 9:37d14c31ff6e 106 }
AzureIoTClient 9:37d14c31ff6e 107
AzureIoTClient 8:83bb166aba73 108 static STRING_HANDLE construct_trace_log_handle(MQTT_CLIENT* mqtt_client)
AzureIoTClient 8:83bb166aba73 109 {
AzureIoTClient 8:83bb166aba73 110 STRING_HANDLE trace_log;
AzureIoTClient 8:83bb166aba73 111 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 112 {
AzureIoTClient 8:83bb166aba73 113 trace_log = STRING_new();
AzureIoTClient 8:83bb166aba73 114 }
AzureIoTClient 8:83bb166aba73 115 else
AzureIoTClient 8:83bb166aba73 116 {
AzureIoTClient 8:83bb166aba73 117 trace_log = NULL;
AzureIoTClient 8:83bb166aba73 118 }
AzureIoTClient 8:83bb166aba73 119 return trace_log;
AzureIoTClient 8:83bb166aba73 120 }
AzureIoTClient 8:83bb166aba73 121
AzureIoTClient 8:83bb166aba73 122 static uint16_t byteutil_read_uint16(uint8_t** buffer, size_t len)
Azure.IoT Build 0:ef4901974abc 123 {
Azure.IoT Build 0:ef4901974abc 124 uint16_t result = 0;
AzureIoTClient 8:83bb166aba73 125 if (buffer != NULL && *buffer != NULL && len >= 2)
Azure.IoT Build 0:ef4901974abc 126 {
AzureIoTClient 8:83bb166aba73 127 result = 256 * (**buffer) + (*(*buffer + 1));
Azure.IoT Build 0:ef4901974abc 128 *buffer += 2; // Move the ptr
Azure.IoT Build 0:ef4901974abc 129 }
AzureIoTClient 8:83bb166aba73 130 else
AzureIoTClient 8:83bb166aba73 131 {
AzureIoTClient 11:a0a6a4cf7812 132 LOG(AZ_LOG_ERROR, LOG_LINE, "byteutil_read_uint16 == NULL or less than 2");
AzureIoTClient 8:83bb166aba73 133 }
Azure.IoT Build 0:ef4901974abc 134 return result;
Azure.IoT Build 0:ef4901974abc 135 }
Azure.IoT Build 0:ef4901974abc 136
Azure.IoT Build 0:ef4901974abc 137 static char* byteutil_readUTF(uint8_t** buffer, size_t* byteLen)
Azure.IoT Build 0:ef4901974abc 138 {
Azure.IoT Build 0:ef4901974abc 139 char* result = NULL;
Azure.IoT Build 0:ef4901974abc 140 if (buffer != NULL)
Azure.IoT Build 0:ef4901974abc 141 {
Azure.IoT Build 0:ef4901974abc 142 // Get the length of the string
AzureIoTClient 8:83bb166aba73 143 uint16_t len = byteutil_read_uint16(buffer, *byteLen);
Azure.IoT Build 0:ef4901974abc 144 if (len > 0)
Azure.IoT Build 0:ef4901974abc 145 {
Azure.IoT Build 0:ef4901974abc 146 result = (char*)malloc(len + 1);
Azure.IoT Build 0:ef4901974abc 147 if (result != NULL)
Azure.IoT Build 0:ef4901974abc 148 {
Azure.IoT Build 0:ef4901974abc 149 (void)memcpy(result, *buffer, len);
Azure.IoT Build 0:ef4901974abc 150 result[len] = '\0';
Azure.IoT Build 0:ef4901974abc 151 *buffer += len;
Azure.IoT Build 0:ef4901974abc 152 if (byteLen != NULL)
Azure.IoT Build 0:ef4901974abc 153 {
Azure.IoT Build 0:ef4901974abc 154 *byteLen = len;
Azure.IoT Build 0:ef4901974abc 155 }
Azure.IoT Build 0:ef4901974abc 156 }
Azure.IoT Build 0:ef4901974abc 157 }
Azure.IoT Build 0:ef4901974abc 158 }
AzureIoTClient 8:83bb166aba73 159 else
AzureIoTClient 8:83bb166aba73 160 {
AzureIoTClient 11:a0a6a4cf7812 161 LOG(AZ_LOG_ERROR, LOG_LINE, "readByte buffer == NULL.");
AzureIoTClient 8:83bb166aba73 162 }
Azure.IoT Build 0:ef4901974abc 163 return result;
Azure.IoT Build 0:ef4901974abc 164 }
Azure.IoT Build 0:ef4901974abc 165
Azure.IoT Build 0:ef4901974abc 166 static uint8_t byteutil_readByte(uint8_t** buffer)
Azure.IoT Build 0:ef4901974abc 167 {
Azure.IoT Build 0:ef4901974abc 168 uint8_t result = 0;
Azure.IoT Build 0:ef4901974abc 169 if (buffer != NULL)
Azure.IoT Build 0:ef4901974abc 170 {
Azure.IoT Build 0:ef4901974abc 171 result = **buffer;
Azure.IoT Build 0:ef4901974abc 172 (*buffer)++;
Azure.IoT Build 0:ef4901974abc 173 }
AzureIoTClient 8:83bb166aba73 174 else
AzureIoTClient 8:83bb166aba73 175 {
AzureIoTClient 11:a0a6a4cf7812 176 LOG(AZ_LOG_ERROR, LOG_LINE, "readByte buffer == NULL.");
AzureIoTClient 8:83bb166aba73 177 }
Azure.IoT Build 0:ef4901974abc 178 return result;
Azure.IoT Build 0:ef4901974abc 179 }
Azure.IoT Build 0:ef4901974abc 180
Azure.IoT Build 0:ef4901974abc 181 static void sendComplete(void* context, IO_SEND_RESULT send_result)
Azure.IoT Build 0:ef4901974abc 182 {
AzureIoTClient 8:83bb166aba73 183 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
AzureIoTClient 9:37d14c31ff6e 184 if (mqtt_client != NULL)
Azure.IoT Build 0:ef4901974abc 185 {
AzureIoTClient 9:37d14c31ff6e 186 if (send_result == IO_SEND_OK)
Azure.IoT Build 0:ef4901974abc 187 {
AzureIoTClient 9:37d14c31ff6e 188 if (mqtt_client->packetState == DISCONNECT_TYPE)
AzureIoTClient 5:34779607059c 189 {
AzureIoTClient 9:37d14c31ff6e 190 /*Codes_SRS_MQTT_CLIENT_07_032: [If the actionResult parameter is of type MQTT_CLIENT_ON_DISCONNECT the the msgInfo value shall be NULL.]*/
AzureIoTClient 9:37d14c31ff6e 191 if (mqtt_client->fnOperationCallback != NULL)
AzureIoTClient 9:37d14c31ff6e 192 {
AzureIoTClient 9:37d14c31ff6e 193 mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_DISCONNECT, NULL, mqtt_client->ctx);
AzureIoTClient 9:37d14c31ff6e 194 }
AzureIoTClient 9:37d14c31ff6e 195 // close the xio
AzureIoTClient 9:37d14c31ff6e 196 close_connection(mqtt_client);
AzureIoTClient 5:34779607059c 197 }
AzureIoTClient 9:37d14c31ff6e 198 }
AzureIoTClient 9:37d14c31ff6e 199 else if (send_result == IO_SEND_ERROR)
AzureIoTClient 9:37d14c31ff6e 200 {
AzureIoTClient 11:a0a6a4cf7812 201 LOG(AZ_LOG_ERROR, LOG_LINE, "MQTT Send Complete Failure send_result: %d", (int)send_result);
AzureIoTClient 9:37d14c31ff6e 202 set_error_callback(mqtt_client, MQTT_CLIENT_COMMUNICATION_ERROR);
Azure.IoT Build 0:ef4901974abc 203 }
Azure.IoT Build 0:ef4901974abc 204 }
AzureIoTClient 5:34779607059c 205 else
AzureIoTClient 5:34779607059c 206 {
AzureIoTClient 11:a0a6a4cf7812 207 LOG(AZ_LOG_ERROR, LOG_LINE, "MQTT Send Complete Failure with NULL mqtt_client");
AzureIoTClient 5:34779607059c 208 }
Azure.IoT Build 0:ef4901974abc 209 }
Azure.IoT Build 0:ef4901974abc 210
AzureIoTClient 28:35eea447689a 211 #ifndef NO_LOGGING
Azure.IoT Build 0:ef4901974abc 212 static const char* retrievePacketType(CONTROL_PACKET_TYPE packet)
Azure.IoT Build 0:ef4901974abc 213 {
Azure.IoT Build 0:ef4901974abc 214 switch (packet&CONNECT_PACKET_MASK)
Azure.IoT Build 0:ef4901974abc 215 {
Azure.IoT Build 0:ef4901974abc 216 case CONNECT_TYPE: return "CONNECT";
Azure.IoT Build 0:ef4901974abc 217 case CONNACK_TYPE: return "CONNACK";
Azure.IoT Build 0:ef4901974abc 218 case PUBLISH_TYPE: return "PUBLISH";
Azure.IoT Build 0:ef4901974abc 219 case PUBACK_TYPE: return "PUBACK";
Azure.IoT Build 0:ef4901974abc 220 case PUBREC_TYPE: return "PUBREC";
Azure.IoT Build 0:ef4901974abc 221 case PUBREL_TYPE: return "PUBREL";
Azure.IoT Build 0:ef4901974abc 222 case SUBSCRIBE_TYPE: return "SUBSCRIBE";
Azure.IoT Build 0:ef4901974abc 223 case SUBACK_TYPE: return "SUBACK";
Azure.IoT Build 0:ef4901974abc 224 case UNSUBSCRIBE_TYPE: return "UNSUBSCRIBE";
Azure.IoT Build 0:ef4901974abc 225 case UNSUBACK_TYPE: return "UNSUBACK";
Azure.IoT Build 0:ef4901974abc 226 case PINGREQ_TYPE: return "PINGREQ";
Azure.IoT Build 0:ef4901974abc 227 case PINGRESP_TYPE: return "PINGRESP";
Azure.IoT Build 0:ef4901974abc 228 case DISCONNECT_TYPE: return "DISCONNECT";
Azure.IoT Build 0:ef4901974abc 229 default:
Azure.IoT Build 0:ef4901974abc 230 case PACKET_TYPE_ERROR:
Azure.IoT Build 0:ef4901974abc 231 case UNKNOWN_TYPE:
Azure.IoT Build 0:ef4901974abc 232 return "UNKNOWN";
Azure.IoT Build 0:ef4901974abc 233 }
Azure.IoT Build 0:ef4901974abc 234 }
AzureIoTClient 28:35eea447689a 235 #endif // NO_LOGGING
Azure.IoT Build 0:ef4901974abc 236
AzureIoTClient 1:8dba42ff9701 237 static void getLogTime(char* timeResult, size_t len)
AzureIoTClient 1:8dba42ff9701 238 {
AzureIoTClient 1:8dba42ff9701 239 if (timeResult != NULL)
AzureIoTClient 1:8dba42ff9701 240 {
AzureIoTClient 8:83bb166aba73 241 time_t agent_time = get_time(NULL);
AzureIoTClient 8:83bb166aba73 242 if (agent_time == (time_t)-1)
AzureIoTClient 1:8dba42ff9701 243 {
AzureIoTClient 1:8dba42ff9701 244 timeResult[0] = '\0';
AzureIoTClient 1:8dba42ff9701 245 }
AzureIoTClient 8:83bb166aba73 246 else
AzureIoTClient 8:83bb166aba73 247 {
AzureIoTClient 8:83bb166aba73 248 struct tm* tmInfo = localtime(&agent_time);
AzureIoTClient 8:83bb166aba73 249 if (tmInfo == NULL)
AzureIoTClient 8:83bb166aba73 250 {
AzureIoTClient 8:83bb166aba73 251 timeResult[0] = '\0';
AzureIoTClient 8:83bb166aba73 252 }
AzureIoTClient 8:83bb166aba73 253 else
AzureIoTClient 8:83bb166aba73 254 {
AzureIoTClient 8:83bb166aba73 255 if (strftime(timeResult, len, "%H:%M:%S", tmInfo) == 0)
AzureIoTClient 8:83bb166aba73 256 {
AzureIoTClient 8:83bb166aba73 257 timeResult[0] = '\0';
AzureIoTClient 8:83bb166aba73 258 }
AzureIoTClient 8:83bb166aba73 259 }
AzureIoTClient 8:83bb166aba73 260 }
AzureIoTClient 1:8dba42ff9701 261 }
AzureIoTClient 1:8dba42ff9701 262 }
AzureIoTClient 1:8dba42ff9701 263
AzureIoTClient 8:83bb166aba73 264 static void log_outgoing_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
Azure.IoT Build 0:ef4901974abc 265 {
AzureIoTClient 8:83bb166aba73 266 if (mqtt_client != NULL && mqtt_client->logTrace && trace_log != NULL)
AzureIoTClient 8:83bb166aba73 267 {
AzureIoTClient 8:83bb166aba73 268 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 8:83bb166aba73 269 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 11:a0a6a4cf7812 270 LOG(AZ_LOG_TRACE, LOG_LINE, "-> %s %s", tmBuffer, STRING_c_str(trace_log));
AzureIoTClient 8:83bb166aba73 271 }
AzureIoTClient 8:83bb166aba73 272 }
AzureIoTClient 8:83bb166aba73 273
AzureIoTClient 18:6d13ad04e8a0 274 static void logOutgoingRawTrace(MQTT_CLIENT* mqtt_client, const uint8_t* data, size_t length)
AzureIoTClient 8:83bb166aba73 275 {
AzureIoTClient 8:83bb166aba73 276 if (mqtt_client != NULL && data != NULL && length > 0 && mqtt_client->rawBytesTrace)
Azure.IoT Build 0:ef4901974abc 277 {
AzureIoTClient 1:8dba42ff9701 278 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 1:8dba42ff9701 279 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 1:8dba42ff9701 280
AzureIoTClient 11:a0a6a4cf7812 281 LOG(AZ_LOG_TRACE, 0, "-> %s %s: ", tmBuffer, retrievePacketType((unsigned char)data[0]));
AzureIoTClient 12:30b08cda82fd 282 size_t index = 0;
AzureIoTClient 12:30b08cda82fd 283 for (index = 0; index < length; index++)
Azure.IoT Build 0:ef4901974abc 284 {
AzureIoTClient 11:a0a6a4cf7812 285 LOG(AZ_LOG_TRACE, 0, "0x%02x ", data[index]);
Azure.IoT Build 0:ef4901974abc 286 }
AzureIoTClient 11:a0a6a4cf7812 287 LOG(AZ_LOG_TRACE, LOG_LINE, "");
Azure.IoT Build 0:ef4901974abc 288 }
Azure.IoT Build 0:ef4901974abc 289 }
Azure.IoT Build 0:ef4901974abc 290
AzureIoTClient 8:83bb166aba73 291 static void log_incoming_trace(MQTT_CLIENT* mqtt_client, STRING_HANDLE trace_log)
AzureIoTClient 8:83bb166aba73 292 {
AzureIoTClient 8:83bb166aba73 293 if (mqtt_client != NULL && mqtt_client->logTrace && trace_log != NULL)
AzureIoTClient 8:83bb166aba73 294 {
AzureIoTClient 8:83bb166aba73 295 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 8:83bb166aba73 296 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 11:a0a6a4cf7812 297 LOG(AZ_LOG_TRACE, LOG_LINE, "<- %s %s", tmBuffer, STRING_c_str(trace_log) );
AzureIoTClient 8:83bb166aba73 298 }
AzureIoTClient 8:83bb166aba73 299 }
AzureIoTClient 8:83bb166aba73 300
AzureIoTClient 8:83bb166aba73 301 static void logIncomingRawTrace(MQTT_CLIENT* mqtt_client, CONTROL_PACKET_TYPE packet, uint8_t flags, const uint8_t* data, size_t length)
Azure.IoT Build 0:ef4901974abc 302 {
AzureIoTClient 6:d9c4702f91ca 303 #ifdef NO_LOGGING
AzureIoTClient 8:83bb166aba73 304 UNUSED(flags);
AzureIoTClient 6:d9c4702f91ca 305 #endif
AzureIoTClient 8:83bb166aba73 306 if (mqtt_client != NULL && mqtt_client->rawBytesTrace)
Azure.IoT Build 0:ef4901974abc 307 {
AzureIoTClient 3:9b4e7158ca0d 308 if (data != NULL && length > 0)
AzureIoTClient 3:9b4e7158ca0d 309 {
AzureIoTClient 3:9b4e7158ca0d 310 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 3:9b4e7158ca0d 311 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 1:8dba42ff9701 312
AzureIoTClient 11:a0a6a4cf7812 313 LOG(AZ_LOG_TRACE, 0, "<- %s %s: 0x%02x 0x%02x ", tmBuffer, retrievePacketType((CONTROL_PACKET_TYPE)packet), (unsigned char)(packet | flags), length);
AzureIoTClient 12:30b08cda82fd 314 size_t index = 0;
AzureIoTClient 12:30b08cda82fd 315 for (index = 0; index < length; index++)
AzureIoTClient 3:9b4e7158ca0d 316 {
AzureIoTClient 11:a0a6a4cf7812 317 LOG(AZ_LOG_TRACE, 0, "0x%02x ", data[index]);
AzureIoTClient 3:9b4e7158ca0d 318 }
AzureIoTClient 11:a0a6a4cf7812 319 LOG(AZ_LOG_TRACE, LOG_LINE, "");
AzureIoTClient 3:9b4e7158ca0d 320 }
AzureIoTClient 3:9b4e7158ca0d 321 else if (packet == PINGRESP_TYPE)
Azure.IoT Build 0:ef4901974abc 322 {
AzureIoTClient 3:9b4e7158ca0d 323 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 3:9b4e7158ca0d 324 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 11:a0a6a4cf7812 325 LOG(AZ_LOG_TRACE, LOG_LINE, "<- %s %s: 0x%02x 0x%02x ", tmBuffer, retrievePacketType((CONTROL_PACKET_TYPE)packet), (unsigned char)(packet | flags), length);
Azure.IoT Build 0:ef4901974abc 326 }
Azure.IoT Build 0:ef4901974abc 327 }
Azure.IoT Build 0:ef4901974abc 328 }
Azure.IoT Build 0:ef4901974abc 329
AzureIoTClient 8:83bb166aba73 330 static int sendPacketItem(MQTT_CLIENT* mqtt_client, const unsigned char* data, size_t length)
Azure.IoT Build 0:ef4901974abc 331 {
Azure.IoT Build 0:ef4901974abc 332 int result;
Azure.IoT Build 0:ef4901974abc 333
AzureIoTClient 8:83bb166aba73 334 if (tickcounter_get_current_ms(mqtt_client->packetTickCntr, &mqtt_client->packetSendTimeMs) != 0)
Azure.IoT Build 0:ef4901974abc 335 {
AzureIoTClient 11:a0a6a4cf7812 336 LOG(AZ_LOG_ERROR, LOG_LINE, "Failure getting current ms tickcounter");
AzureIoTClient 15:ec5a36121959 337 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 338 }
Azure.IoT Build 0:ef4901974abc 339 else
Azure.IoT Build 0:ef4901974abc 340 {
AzureIoTClient 8:83bb166aba73 341 result = xio_send(mqtt_client->xioHandle, (const void*)data, length, sendComplete, mqtt_client);
Azure.IoT Build 0:ef4901974abc 342 if (result != 0)
Azure.IoT Build 0:ef4901974abc 343 {
AzureIoTClient 11:a0a6a4cf7812 344 LOG(AZ_LOG_ERROR, LOG_LINE, "%d: Failure sending control packet data", result);
AzureIoTClient 15:ec5a36121959 345 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 346 }
Azure.IoT Build 4:e7167dabd6e4 347 else
Azure.IoT Build 4:e7167dabd6e4 348 {
AzureIoTClient 18:6d13ad04e8a0 349 logOutgoingRawTrace(mqtt_client, (const uint8_t*)data, length);
Azure.IoT Build 4:e7167dabd6e4 350 }
Azure.IoT Build 0:ef4901974abc 351 }
Azure.IoT Build 0:ef4901974abc 352 return result;
Azure.IoT Build 0:ef4901974abc 353 }
Azure.IoT Build 0:ef4901974abc 354
Azure.IoT Build 0:ef4901974abc 355 static void onOpenComplete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:ef4901974abc 356 {
AzureIoTClient 8:83bb166aba73 357 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
AzureIoTClient 8:83bb166aba73 358 if (mqtt_client != NULL)
Azure.IoT Build 0:ef4901974abc 359 {
AzureIoTClient 8:83bb166aba73 360 if (open_result == IO_OPEN_OK && !mqtt_client->socketConnected)
Azure.IoT Build 0:ef4901974abc 361 {
AzureIoTClient 8:83bb166aba73 362 mqtt_client->packetState = CONNECT_TYPE;
AzureIoTClient 8:83bb166aba73 363 mqtt_client->socketConnected = true;
AzureIoTClient 8:83bb166aba73 364
AzureIoTClient 8:83bb166aba73 365 STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
AzureIoTClient 8:83bb166aba73 366
Azure.IoT Build 0:ef4901974abc 367 // Send the Connect packet
AzureIoTClient 8:83bb166aba73 368 BUFFER_HANDLE connPacket = mqtt_codec_connect(&mqtt_client->mqttOptions, trace_log);
Azure.IoT Build 0:ef4901974abc 369 if (connPacket == NULL)
Azure.IoT Build 0:ef4901974abc 370 {
AzureIoTClient 11:a0a6a4cf7812 371 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_codec_connect failed");
Azure.IoT Build 0:ef4901974abc 372 }
Azure.IoT Build 0:ef4901974abc 373 else
Azure.IoT Build 0:ef4901974abc 374 {
AzureIoTClient 13:3c202001e4ba 375 size_t size = BUFFER_length(connPacket);
Azure.IoT Build 0:ef4901974abc 376 /*Codes_SRS_MQTT_CLIENT_07_009: [On success mqtt_client_connect shall send the MQTT CONNECT to the endpoint.]*/
AzureIoTClient 13:3c202001e4ba 377 if (sendPacketItem(mqtt_client, BUFFER_u_char(connPacket), size) != 0)
Azure.IoT Build 0:ef4901974abc 378 {
AzureIoTClient 11:a0a6a4cf7812 379 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_codec_connect failed");
Azure.IoT Build 0:ef4901974abc 380 }
AzureIoTClient 8:83bb166aba73 381 else
AzureIoTClient 8:83bb166aba73 382 {
AzureIoTClient 8:83bb166aba73 383 log_outgoing_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 384 }
Azure.IoT Build 0:ef4901974abc 385 BUFFER_delete(connPacket);
Azure.IoT Build 0:ef4901974abc 386 }
AzureIoTClient 8:83bb166aba73 387 if (trace_log != NULL)
AzureIoTClient 8:83bb166aba73 388 {
AzureIoTClient 8:83bb166aba73 389 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 390 }
Azure.IoT Build 0:ef4901974abc 391 }
AzureIoTClient 8:83bb166aba73 392 else
Azure.IoT Build 0:ef4901974abc 393 {
AzureIoTClient 9:37d14c31ff6e 394 if (mqtt_client->socketConnected == false && mqtt_client->fnOnErrorCallBack)
AzureIoTClient 8:83bb166aba73 395 {
AzureIoTClient 9:37d14c31ff6e 396 mqtt_client->fnOnErrorCallBack(mqtt_client, MQTT_CLIENT_CONNECTION_ERROR, mqtt_client->errorCBCtx);
AzureIoTClient 8:83bb166aba73 397 }
AzureIoTClient 9:37d14c31ff6e 398 close_connection(mqtt_client);
Azure.IoT Build 0:ef4901974abc 399 }
Azure.IoT Build 0:ef4901974abc 400 }
AzureIoTClient 8:83bb166aba73 401 else
AzureIoTClient 8:83bb166aba73 402 {
AzureIoTClient 11:a0a6a4cf7812 403 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client is NULL");
AzureIoTClient 8:83bb166aba73 404 }
Azure.IoT Build 0:ef4901974abc 405 }
Azure.IoT Build 0:ef4901974abc 406
Azure.IoT Build 0:ef4901974abc 407 static void onBytesReceived(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:ef4901974abc 408 {
AzureIoTClient 8:83bb166aba73 409 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
AzureIoTClient 8:83bb166aba73 410 if (mqtt_client != NULL)
Azure.IoT Build 0:ef4901974abc 411 {
AzureIoTClient 8:83bb166aba73 412 if (mqtt_codec_bytesReceived(mqtt_client->codec_handle, buffer, size) != 0)
Azure.IoT Build 0:ef4901974abc 413 {
AzureIoTClient 9:37d14c31ff6e 414 set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
Azure.IoT Build 0:ef4901974abc 415 }
Azure.IoT Build 0:ef4901974abc 416 }
AzureIoTClient 8:83bb166aba73 417 else
AzureIoTClient 8:83bb166aba73 418 {
AzureIoTClient 11:a0a6a4cf7812 419 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client is NULL");
AzureIoTClient 8:83bb166aba73 420 }
Azure.IoT Build 0:ef4901974abc 421 }
Azure.IoT Build 0:ef4901974abc 422
Azure.IoT Build 0:ef4901974abc 423 static void onIoError(void* context)
Azure.IoT Build 0:ef4901974abc 424 {
AzureIoTClient 8:83bb166aba73 425 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
AzureIoTClient 8:83bb166aba73 426 if (mqtt_client != NULL && mqtt_client->fnOperationCallback)
Azure.IoT Build 0:ef4901974abc 427 {
AzureIoTClient 9:37d14c31ff6e 428 /*Codes_SRS_MQTT_CLIENT_07_032: [If the actionResult parameter is of type MQTT_CLIENT_ON_DISCONNECT the the msgInfo value shall be NULL.]*/
AzureIoTClient 8:83bb166aba73 429 /* Codes_SRS_MQTT_CLIENT_07_036: [ If an error is encountered by the ioHandle the mqtt_client shall call xio_close. ] */
AzureIoTClient 9:37d14c31ff6e 430 set_error_callback(mqtt_client, MQTT_CLIENT_CONNECTION_ERROR);
AzureIoTClient 8:83bb166aba73 431 }
AzureIoTClient 8:83bb166aba73 432 else
AzureIoTClient 8:83bb166aba73 433 {
AzureIoTClient 11:a0a6a4cf7812 434 LOG(AZ_LOG_ERROR, LOG_LINE, "Error invalid parameter: mqtt_client: %p", mqtt_client);
Azure.IoT Build 0:ef4901974abc 435 }
Azure.IoT Build 0:ef4901974abc 436 }
Azure.IoT Build 0:ef4901974abc 437
AzureIoTClient 14:4b5b4dccfc8b 438 static void clear_mqtt_options(MQTT_CLIENT* mqtt_client)
AzureIoTClient 14:4b5b4dccfc8b 439 {
AzureIoTClient 18:6d13ad04e8a0 440 if (mqtt_client->mqttOptions.clientId != NULL)
AzureIoTClient 18:6d13ad04e8a0 441 {
AzureIoTClient 18:6d13ad04e8a0 442 free(mqtt_client->mqttOptions.clientId);
AzureIoTClient 18:6d13ad04e8a0 443 mqtt_client->mqttOptions.clientId = NULL;
AzureIoTClient 18:6d13ad04e8a0 444 }
AzureIoTClient 18:6d13ad04e8a0 445
AzureIoTClient 18:6d13ad04e8a0 446 if (mqtt_client->mqttOptions.willTopic != NULL)
AzureIoTClient 18:6d13ad04e8a0 447 {
AzureIoTClient 18:6d13ad04e8a0 448 free(mqtt_client->mqttOptions.willTopic);
AzureIoTClient 18:6d13ad04e8a0 449 mqtt_client->mqttOptions.willTopic = NULL;
AzureIoTClient 18:6d13ad04e8a0 450 }
AzureIoTClient 18:6d13ad04e8a0 451
AzureIoTClient 18:6d13ad04e8a0 452 if (mqtt_client->mqttOptions.willMessage != NULL)
AzureIoTClient 18:6d13ad04e8a0 453 {
AzureIoTClient 18:6d13ad04e8a0 454 free(mqtt_client->mqttOptions.willMessage);
AzureIoTClient 18:6d13ad04e8a0 455 mqtt_client->mqttOptions.willMessage = NULL;
AzureIoTClient 18:6d13ad04e8a0 456 }
AzureIoTClient 18:6d13ad04e8a0 457
AzureIoTClient 18:6d13ad04e8a0 458 if (mqtt_client->mqttOptions.username != NULL)
AzureIoTClient 18:6d13ad04e8a0 459 {
AzureIoTClient 18:6d13ad04e8a0 460 free(mqtt_client->mqttOptions.username);
AzureIoTClient 18:6d13ad04e8a0 461 mqtt_client->mqttOptions.username = NULL;
AzureIoTClient 18:6d13ad04e8a0 462 }
AzureIoTClient 18:6d13ad04e8a0 463
AzureIoTClient 18:6d13ad04e8a0 464 if (mqtt_client->mqttOptions.password != NULL)
AzureIoTClient 18:6d13ad04e8a0 465 {
AzureIoTClient 18:6d13ad04e8a0 466 free(mqtt_client->mqttOptions.password);
AzureIoTClient 18:6d13ad04e8a0 467 mqtt_client->mqttOptions.password = NULL;
AzureIoTClient 18:6d13ad04e8a0 468 }
AzureIoTClient 14:4b5b4dccfc8b 469 }
AzureIoTClient 14:4b5b4dccfc8b 470
AzureIoTClient 8:83bb166aba73 471 static int cloneMqttOptions(MQTT_CLIENT* mqtt_client, const MQTT_CLIENT_OPTIONS* mqttOptions)
Azure.IoT Build 0:ef4901974abc 472 {
Azure.IoT Build 0:ef4901974abc 473 int result = 0;
AzureIoTClient 18:6d13ad04e8a0 474
Azure.IoT Build 0:ef4901974abc 475 if (mqttOptions->clientId != NULL)
Azure.IoT Build 0:ef4901974abc 476 {
AzureIoTClient 18:6d13ad04e8a0 477 char* clientId;
AzureIoTClient 18:6d13ad04e8a0 478
AzureIoTClient 18:6d13ad04e8a0 479 if (mallocAndStrcpy_s(&clientId, mqttOptions->clientId) != 0)
Azure.IoT Build 0:ef4901974abc 480 {
AzureIoTClient 15:ec5a36121959 481 result = __FAILURE__;
AzureIoTClient 11:a0a6a4cf7812 482 LOG(AZ_LOG_ERROR, LOG_LINE, "mallocAndStrcpy_s clientId");
Azure.IoT Build 0:ef4901974abc 483 }
AzureIoTClient 18:6d13ad04e8a0 484 else
AzureIoTClient 18:6d13ad04e8a0 485 {
AzureIoTClient 18:6d13ad04e8a0 486 if (mqtt_client->mqttOptions.clientId != NULL)
AzureIoTClient 18:6d13ad04e8a0 487 {
AzureIoTClient 18:6d13ad04e8a0 488 free(mqtt_client->mqttOptions.clientId);
AzureIoTClient 18:6d13ad04e8a0 489 }
AzureIoTClient 18:6d13ad04e8a0 490
AzureIoTClient 18:6d13ad04e8a0 491 mqtt_client->mqttOptions.clientId = clientId;
AzureIoTClient 18:6d13ad04e8a0 492 }
Azure.IoT Build 0:ef4901974abc 493 }
Azure.IoT Build 0:ef4901974abc 494 if (result == 0 && mqttOptions->willTopic != NULL)
Azure.IoT Build 0:ef4901974abc 495 {
AzureIoTClient 18:6d13ad04e8a0 496 char* willTopic;
AzureIoTClient 18:6d13ad04e8a0 497
AzureIoTClient 18:6d13ad04e8a0 498 if (mallocAndStrcpy_s(&willTopic, mqttOptions->willTopic) != 0)
Azure.IoT Build 0:ef4901974abc 499 {
AzureIoTClient 15:ec5a36121959 500 result = __FAILURE__;
AzureIoTClient 11:a0a6a4cf7812 501 LOG(AZ_LOG_ERROR, LOG_LINE, "mallocAndStrcpy_s willTopic");
Azure.IoT Build 0:ef4901974abc 502 }
AzureIoTClient 18:6d13ad04e8a0 503 else
AzureIoTClient 18:6d13ad04e8a0 504 {
AzureIoTClient 18:6d13ad04e8a0 505 if (mqtt_client->mqttOptions.willTopic != NULL)
AzureIoTClient 18:6d13ad04e8a0 506 {
AzureIoTClient 18:6d13ad04e8a0 507 free(mqtt_client->mqttOptions.willTopic);
AzureIoTClient 18:6d13ad04e8a0 508 }
AzureIoTClient 18:6d13ad04e8a0 509
AzureIoTClient 18:6d13ad04e8a0 510 mqtt_client->mqttOptions.willTopic = willTopic;
AzureIoTClient 18:6d13ad04e8a0 511 }
Azure.IoT Build 0:ef4901974abc 512 }
Azure.IoT Build 0:ef4901974abc 513 if (result == 0 && mqttOptions->willMessage != NULL)
Azure.IoT Build 0:ef4901974abc 514 {
AzureIoTClient 18:6d13ad04e8a0 515 char* willMessage;
AzureIoTClient 18:6d13ad04e8a0 516
AzureIoTClient 18:6d13ad04e8a0 517 if (mallocAndStrcpy_s(&willMessage, mqttOptions->willMessage) != 0)
Azure.IoT Build 0:ef4901974abc 518 {
AzureIoTClient 11:a0a6a4cf7812 519 LOG(AZ_LOG_ERROR, LOG_LINE, "mallocAndStrcpy_s willMessage");
AzureIoTClient 15:ec5a36121959 520 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 521 }
AzureIoTClient 18:6d13ad04e8a0 522 else
AzureIoTClient 18:6d13ad04e8a0 523 {
AzureIoTClient 18:6d13ad04e8a0 524 if (mqtt_client->mqttOptions.willMessage != NULL)
AzureIoTClient 18:6d13ad04e8a0 525 {
AzureIoTClient 18:6d13ad04e8a0 526 free(mqtt_client->mqttOptions.willMessage);
AzureIoTClient 18:6d13ad04e8a0 527 }
AzureIoTClient 18:6d13ad04e8a0 528
AzureIoTClient 18:6d13ad04e8a0 529 mqtt_client->mqttOptions.willMessage = willMessage;
AzureIoTClient 18:6d13ad04e8a0 530 }
Azure.IoT Build 0:ef4901974abc 531 }
Azure.IoT Build 0:ef4901974abc 532 if (result == 0 && mqttOptions->username != NULL)
Azure.IoT Build 0:ef4901974abc 533 {
AzureIoTClient 18:6d13ad04e8a0 534 char* username;
AzureIoTClient 18:6d13ad04e8a0 535
AzureIoTClient 18:6d13ad04e8a0 536 if (mallocAndStrcpy_s(&username, mqttOptions->username) != 0)
Azure.IoT Build 0:ef4901974abc 537 {
AzureIoTClient 11:a0a6a4cf7812 538 LOG(AZ_LOG_ERROR, LOG_LINE, "mallocAndStrcpy_s username");
AzureIoTClient 15:ec5a36121959 539 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 540 }
AzureIoTClient 18:6d13ad04e8a0 541 else
AzureIoTClient 18:6d13ad04e8a0 542 {
AzureIoTClient 18:6d13ad04e8a0 543 if (mqtt_client->mqttOptions.username != NULL)
AzureIoTClient 18:6d13ad04e8a0 544 {
AzureIoTClient 18:6d13ad04e8a0 545 free(mqtt_client->mqttOptions.username);
AzureIoTClient 18:6d13ad04e8a0 546 }
AzureIoTClient 18:6d13ad04e8a0 547
AzureIoTClient 18:6d13ad04e8a0 548 mqtt_client->mqttOptions.username = username;
AzureIoTClient 18:6d13ad04e8a0 549 }
Azure.IoT Build 0:ef4901974abc 550 }
Azure.IoT Build 0:ef4901974abc 551 if (result == 0 && mqttOptions->password != NULL)
Azure.IoT Build 0:ef4901974abc 552 {
AzureIoTClient 18:6d13ad04e8a0 553 char* password;
AzureIoTClient 18:6d13ad04e8a0 554
AzureIoTClient 18:6d13ad04e8a0 555 if (mallocAndStrcpy_s(&password, mqttOptions->password) != 0)
Azure.IoT Build 0:ef4901974abc 556 {
AzureIoTClient 11:a0a6a4cf7812 557 LOG(AZ_LOG_ERROR, LOG_LINE, "mallocAndStrcpy_s password");
AzureIoTClient 15:ec5a36121959 558 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 559 }
AzureIoTClient 18:6d13ad04e8a0 560 else
AzureIoTClient 18:6d13ad04e8a0 561 {
AzureIoTClient 18:6d13ad04e8a0 562 if (mqtt_client->mqttOptions.password != NULL)
AzureIoTClient 18:6d13ad04e8a0 563 {
AzureIoTClient 18:6d13ad04e8a0 564 free(mqtt_client->mqttOptions.password);
AzureIoTClient 18:6d13ad04e8a0 565 }
AzureIoTClient 18:6d13ad04e8a0 566
AzureIoTClient 18:6d13ad04e8a0 567 mqtt_client->mqttOptions.password = password;
AzureIoTClient 18:6d13ad04e8a0 568 }
Azure.IoT Build 0:ef4901974abc 569 }
Azure.IoT Build 0:ef4901974abc 570 if (result == 0)
Azure.IoT Build 0:ef4901974abc 571 {
AzureIoTClient 8:83bb166aba73 572 mqtt_client->mqttOptions.keepAliveInterval = mqttOptions->keepAliveInterval;
AzureIoTClient 8:83bb166aba73 573 mqtt_client->mqttOptions.messageRetain = mqttOptions->messageRetain;
AzureIoTClient 8:83bb166aba73 574 mqtt_client->mqttOptions.useCleanSession = mqttOptions->useCleanSession;
AzureIoTClient 8:83bb166aba73 575 mqtt_client->mqttOptions.qualityOfServiceValue = mqttOptions->qualityOfServiceValue;
Azure.IoT Build 0:ef4901974abc 576 }
Azure.IoT Build 0:ef4901974abc 577 else
Azure.IoT Build 0:ef4901974abc 578 {
AzureIoTClient 14:4b5b4dccfc8b 579 clear_mqtt_options(mqtt_client);
Azure.IoT Build 0:ef4901974abc 580 }
Azure.IoT Build 0:ef4901974abc 581 return result;
Azure.IoT Build 0:ef4901974abc 582 }
Azure.IoT Build 0:ef4901974abc 583
Azure.IoT Build 0:ef4901974abc 584 static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int flags, BUFFER_HANDLE headerData)
Azure.IoT Build 0:ef4901974abc 585 {
AzureIoTClient 8:83bb166aba73 586 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)context;
AzureIoTClient 8:83bb166aba73 587 if ((mqtt_client != NULL && headerData != NULL) || packet == PINGRESP_TYPE)
Azure.IoT Build 0:ef4901974abc 588 {
AzureIoTClient 29:7bb0aae34648 589 size_t len = 0;
AzureIoTClient 29:7bb0aae34648 590 uint8_t* iterator = NULL;
Azure.IoT Build 0:ef4901974abc 591
AzureIoTClient 29:7bb0aae34648 592 if (headerData != NULL)
AzureIoTClient 29:7bb0aae34648 593 {
AzureIoTClient 29:7bb0aae34648 594 len = BUFFER_length(headerData);
AzureIoTClient 29:7bb0aae34648 595 iterator = BUFFER_u_char(headerData);
AzureIoTClient 29:7bb0aae34648 596 }
AzureIoTClient 8:83bb166aba73 597 logIncomingRawTrace(mqtt_client, packet, (uint8_t)flags, iterator, len);
AzureIoTClient 3:9b4e7158ca0d 598 if ((iterator != NULL && len > 0) || packet == PINGRESP_TYPE)
Azure.IoT Build 0:ef4901974abc 599 {
Azure.IoT Build 0:ef4901974abc 600 switch (packet)
Azure.IoT Build 0:ef4901974abc 601 {
AzureIoTClient 3:9b4e7158ca0d 602 case CONNACK_TYPE:
Azure.IoT Build 0:ef4901974abc 603 {
AzureIoTClient 8:83bb166aba73 604 if (mqtt_client->fnOperationCallback != NULL)
AzureIoTClient 3:9b4e7158ca0d 605 {
AzureIoTClient 8:83bb166aba73 606 STRING_HANDLE trace_log = NULL;
AzureIoTClient 8:83bb166aba73 607
AzureIoTClient 3:9b4e7158ca0d 608 /*Codes_SRS_MQTT_CLIENT_07_028: [If the actionResult parameter is of type CONNECT_ACK then the msgInfo value shall be a CONNECT_ACK structure.]*/
AzureIoTClient 3:9b4e7158ca0d 609 CONNECT_ACK connack = { 0 };
AzureIoTClient 3:9b4e7158ca0d 610 connack.isSessionPresent = (byteutil_readByte(&iterator) == 0x1) ? true : false;
AzureIoTClient 28:35eea447689a 611 uint8_t rc = byteutil_readByte(&iterator);
AzureIoTClient 28:35eea447689a 612 connack.returnCode =
AzureIoTClient 28:35eea447689a 613 (rc < ((uint8_t)CONN_REFUSED_UNKNOWN)) ?
AzureIoTClient 28:35eea447689a 614 (CONNECT_RETURN_CODE)rc : CONN_REFUSED_UNKNOWN;
Azure.IoT Build 0:ef4901974abc 615
AzureIoTClient 8:83bb166aba73 616 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 617 {
AzureIoTClient 8:83bb166aba73 618 trace_log = STRING_construct_sprintf("CONNACK | SESSION_PRESENT: %s | RETURN_CODE: 0x%x", connack.isSessionPresent ? TRUE_CONST : FALSE_CONST, connack.returnCode);
AzureIoTClient 8:83bb166aba73 619 log_incoming_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 620 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 621 }
AzureIoTClient 8:83bb166aba73 622 mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_CONNACK, (void*)&connack, mqtt_client->ctx);
AzureIoTClient 3:9b4e7158ca0d 623
AzureIoTClient 3:9b4e7158ca0d 624 if (connack.returnCode == CONNECTION_ACCEPTED)
AzureIoTClient 3:9b4e7158ca0d 625 {
AzureIoTClient 8:83bb166aba73 626 mqtt_client->clientConnected = true;
AzureIoTClient 3:9b4e7158ca0d 627 }
Azure.IoT Build 0:ef4901974abc 628 }
AzureIoTClient 8:83bb166aba73 629 else
AzureIoTClient 8:83bb166aba73 630 {
AzureIoTClient 11:a0a6a4cf7812 631 LOG(AZ_LOG_ERROR, LOG_LINE, "fnOperationCallback NULL");
AzureIoTClient 8:83bb166aba73 632 }
AzureIoTClient 3:9b4e7158ca0d 633 break;
Azure.IoT Build 0:ef4901974abc 634 }
AzureIoTClient 3:9b4e7158ca0d 635 case PUBLISH_TYPE:
Azure.IoT Build 0:ef4901974abc 636 {
AzureIoTClient 8:83bb166aba73 637 if (mqtt_client->fnMessageRecv != NULL)
AzureIoTClient 3:9b4e7158ca0d 638 {
AzureIoTClient 8:83bb166aba73 639 STRING_HANDLE trace_log = NULL;
AzureIoTClient 8:83bb166aba73 640
AzureIoTClient 3:9b4e7158ca0d 641 bool isDuplicateMsg = (flags & DUPLICATE_FLAG_MASK) ? true : false;
AzureIoTClient 3:9b4e7158ca0d 642 bool isRetainMsg = (flags & RETAIN_FLAG_MASK) ? true : false;
AzureIoTClient 3:9b4e7158ca0d 643 QOS_VALUE qosValue = (flags == 0) ? DELIVER_AT_MOST_ONCE : (flags & QOS_LEAST_ONCE_FLAG_MASK) ? DELIVER_AT_LEAST_ONCE : DELIVER_EXACTLY_ONCE;
AzureIoTClient 3:9b4e7158ca0d 644
AzureIoTClient 8:83bb166aba73 645 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 646 {
AzureIoTClient 28:35eea447689a 647 trace_log = STRING_construct_sprintf("PUBLISH | IS_DUP: %s | RETAIN: %d | QOS: %s", isDuplicateMsg ? TRUE_CONST : FALSE_CONST,
AzureIoTClient 8:83bb166aba73 648 isRetainMsg ? 1 : 0, ENUM_TO_STRING(QOS_VALUE, qosValue) );
AzureIoTClient 8:83bb166aba73 649 }
AzureIoTClient 8:83bb166aba73 650
AzureIoTClient 3:9b4e7158ca0d 651 uint8_t* initialPos = iterator;
AzureIoTClient 8:83bb166aba73 652 size_t length = len - (iterator - initialPos);
AzureIoTClient 8:83bb166aba73 653 char* topicName = byteutil_readUTF(&iterator, &length);
AzureIoTClient 5:34779607059c 654 if (topicName == NULL)
AzureIoTClient 3:9b4e7158ca0d 655 {
AzureIoTClient 11:a0a6a4cf7812 656 LOG(AZ_LOG_ERROR, LOG_LINE, "Publish MSG: failure reading topic name");
AzureIoTClient 9:37d14c31ff6e 657 set_error_callback(mqtt_client, MQTT_CLIENT_PARSE_ERROR);
AzureIoTClient 8:83bb166aba73 658 if (trace_log != NULL)
AzureIoTClient 8:83bb166aba73 659 {
AzureIoTClient 8:83bb166aba73 660 STRING_delete(trace_log);
AzureIoTClient 5:34779607059c 661 }
AzureIoTClient 3:9b4e7158ca0d 662 }
AzureIoTClient 3:9b4e7158ca0d 663 else
AzureIoTClient 3:9b4e7158ca0d 664 {
AzureIoTClient 8:83bb166aba73 665 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 666 {
AzureIoTClient 8:83bb166aba73 667 STRING_sprintf(trace_log, " | TOPIC_NAME: %s", topicName);
AzureIoTClient 8:83bb166aba73 668 }
AzureIoTClient 5:34779607059c 669 uint16_t packetId = 0;
AzureIoTClient 8:83bb166aba73 670 length = len - (iterator - initialPos);
AzureIoTClient 5:34779607059c 671 if (qosValue != DELIVER_AT_MOST_ONCE)
AzureIoTClient 5:34779607059c 672 {
AzureIoTClient 8:83bb166aba73 673 packetId = byteutil_read_uint16(&iterator, length);
AzureIoTClient 8:83bb166aba73 674 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 675 {
AzureIoTClient 8:83bb166aba73 676 STRING_sprintf(trace_log, " | PACKET_ID: %"PRIu16, packetId);
AzureIoTClient 8:83bb166aba73 677 }
AzureIoTClient 5:34779607059c 678 }
AzureIoTClient 8:83bb166aba73 679 length = len - (iterator - initialPos);
AzureIoTClient 3:9b4e7158ca0d 680
AzureIoTClient 5:34779607059c 681 MQTT_MESSAGE_HANDLE msgHandle = mqttmessage_create(packetId, topicName, qosValue, iterator, length);
AzureIoTClient 5:34779607059c 682 if (msgHandle == NULL)
AzureIoTClient 3:9b4e7158ca0d 683 {
AzureIoTClient 11:a0a6a4cf7812 684 LOG(AZ_LOG_ERROR, LOG_LINE, "failure in mqttmessage_create");
AzureIoTClient 9:37d14c31ff6e 685 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 8:83bb166aba73 686 if (trace_log != NULL) {
AzureIoTClient 8:83bb166aba73 687 STRING_delete(trace_log);
AzureIoTClient 5:34779607059c 688 }
AzureIoTClient 3:9b4e7158ca0d 689 }
AzureIoTClient 5:34779607059c 690 else
AzureIoTClient 3:9b4e7158ca0d 691 {
AzureIoTClient 5:34779607059c 692 if (mqttmessage_setIsDuplicateMsg(msgHandle, isDuplicateMsg) != 0 ||
AzureIoTClient 5:34779607059c 693 mqttmessage_setIsRetained(msgHandle, isRetainMsg) != 0)
AzureIoTClient 5:34779607059c 694 {
AzureIoTClient 11:a0a6a4cf7812 695 LOG(AZ_LOG_ERROR, LOG_LINE, "failure setting mqtt message property");
AzureIoTClient 9:37d14c31ff6e 696 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 8:83bb166aba73 697 if (trace_log != NULL) {
AzureIoTClient 8:83bb166aba73 698 STRING_delete(trace_log);
AzureIoTClient 5:34779607059c 699 }
AzureIoTClient 5:34779607059c 700 }
AzureIoTClient 5:34779607059c 701 else
AzureIoTClient 5:34779607059c 702 {
AzureIoTClient 8:83bb166aba73 703 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 704 {
AzureIoTClient 8:83bb166aba73 705 STRING_sprintf(trace_log, " | PAYLOAD_LEN: %zu", length);
AzureIoTClient 8:83bb166aba73 706 log_incoming_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 707 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 708 }
AzureIoTClient 8:83bb166aba73 709
AzureIoTClient 8:83bb166aba73 710 mqtt_client->fnMessageRecv(msgHandle, mqtt_client->ctx);
AzureIoTClient 5:34779607059c 711
AzureIoTClient 5:34779607059c 712 BUFFER_HANDLE pubRel = NULL;
AzureIoTClient 5:34779607059c 713 if (qosValue == DELIVER_EXACTLY_ONCE)
AzureIoTClient 5:34779607059c 714 {
AzureIoTClient 5:34779607059c 715 pubRel = mqtt_codec_publishReceived(packetId);
AzureIoTClient 5:34779607059c 716 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 717 {
AzureIoTClient 11:a0a6a4cf7812 718 LOG(AZ_LOG_ERROR, LOG_LINE, "Failed to allocate publish receive message.");
AzureIoTClient 9:37d14c31ff6e 719 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 5:34779607059c 720 }
AzureIoTClient 5:34779607059c 721 }
AzureIoTClient 5:34779607059c 722 else if (qosValue == DELIVER_AT_LEAST_ONCE)
AzureIoTClient 5:34779607059c 723 {
AzureIoTClient 5:34779607059c 724 pubRel = mqtt_codec_publishAck(packetId);
AzureIoTClient 5:34779607059c 725 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 726 {
AzureIoTClient 11:a0a6a4cf7812 727 LOG(AZ_LOG_ERROR, LOG_LINE, "Failed to allocate publish ack message.");
AzureIoTClient 9:37d14c31ff6e 728 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 5:34779607059c 729 }
AzureIoTClient 5:34779607059c 730 }
AzureIoTClient 5:34779607059c 731 if (pubRel != NULL)
AzureIoTClient 5:34779607059c 732 {
AzureIoTClient 13:3c202001e4ba 733 size_t size = BUFFER_length(pubRel);
AzureIoTClient 13:3c202001e4ba 734 (void)sendPacketItem(mqtt_client, BUFFER_u_char(pubRel), size);
AzureIoTClient 5:34779607059c 735 BUFFER_delete(pubRel);
AzureIoTClient 5:34779607059c 736 }
AzureIoTClient 5:34779607059c 737 }
AzureIoTClient 5:34779607059c 738 mqttmessage_destroy(msgHandle);
AzureIoTClient 3:9b4e7158ca0d 739 }
AzureIoTClient 3:9b4e7158ca0d 740 free(topicName);
AzureIoTClient 3:9b4e7158ca0d 741 }
Azure.IoT Build 0:ef4901974abc 742 }
AzureIoTClient 3:9b4e7158ca0d 743 break;
AzureIoTClient 3:9b4e7158ca0d 744 }
AzureIoTClient 3:9b4e7158ca0d 745 case PUBACK_TYPE:
AzureIoTClient 3:9b4e7158ca0d 746 case PUBREC_TYPE:
AzureIoTClient 3:9b4e7158ca0d 747 case PUBREL_TYPE:
AzureIoTClient 3:9b4e7158ca0d 748 case PUBCOMP_TYPE:
AzureIoTClient 3:9b4e7158ca0d 749 {
AzureIoTClient 8:83bb166aba73 750 if (mqtt_client->fnOperationCallback)
Azure.IoT Build 0:ef4901974abc 751 {
AzureIoTClient 8:83bb166aba73 752 STRING_HANDLE trace_log = NULL;
AzureIoTClient 8:83bb166aba73 753
AzureIoTClient 3:9b4e7158ca0d 754 /*Codes_SRS_MQTT_CLIENT_07_029: [If the actionResult parameter are of types PUBACK_TYPE, PUBREC_TYPE, PUBREL_TYPE or PUBCOMP_TYPE then the msgInfo value shall be a PUBLISH_ACK structure.]*/
AzureIoTClient 3:9b4e7158ca0d 755 MQTT_CLIENT_EVENT_RESULT action = (packet == PUBACK_TYPE) ? MQTT_CLIENT_ON_PUBLISH_ACK :
AzureIoTClient 3:9b4e7158ca0d 756 (packet == PUBREC_TYPE) ? MQTT_CLIENT_ON_PUBLISH_RECV :
AzureIoTClient 3:9b4e7158ca0d 757 (packet == PUBREL_TYPE) ? MQTT_CLIENT_ON_PUBLISH_REL : MQTT_CLIENT_ON_PUBLISH_COMP;
AzureIoTClient 3:9b4e7158ca0d 758
AzureIoTClient 3:9b4e7158ca0d 759 PUBLISH_ACK publish_ack = { 0 };
AzureIoTClient 8:83bb166aba73 760 publish_ack.packetId = byteutil_read_uint16(&iterator, len);
AzureIoTClient 8:83bb166aba73 761
AzureIoTClient 8:83bb166aba73 762 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 763 {
AzureIoTClient 8:83bb166aba73 764 trace_log = STRING_construct_sprintf("%s | PACKET_ID: %"PRIu16, packet == PUBACK_TYPE ? "PUBACK" : (packet == PUBREC_TYPE) ? "PUBREC" : (packet == PUBREL_TYPE) ? "PUBREL" : "PUBCOMP",
AzureIoTClient 8:83bb166aba73 765 publish_ack.packetId);
AzureIoTClient 8:83bb166aba73 766
AzureIoTClient 8:83bb166aba73 767 log_incoming_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 768 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 769 }
Azure.IoT Build 0:ef4901974abc 770
Azure.IoT Build 0:ef4901974abc 771 BUFFER_HANDLE pubRel = NULL;
AzureIoTClient 8:83bb166aba73 772 mqtt_client->fnOperationCallback(mqtt_client, action, (void*)&publish_ack, mqtt_client->ctx);
AzureIoTClient 3:9b4e7158ca0d 773 if (packet == PUBREC_TYPE)
Azure.IoT Build 0:ef4901974abc 774 {
AzureIoTClient 3:9b4e7158ca0d 775 pubRel = mqtt_codec_publishRelease(publish_ack.packetId);
AzureIoTClient 5:34779607059c 776 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 777 {
AzureIoTClient 11:a0a6a4cf7812 778 LOG(AZ_LOG_ERROR, LOG_LINE, "Failed to allocate publish release message.");
AzureIoTClient 9:37d14c31ff6e 779 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 5:34779607059c 780 }
Azure.IoT Build 0:ef4901974abc 781 }
AzureIoTClient 3:9b4e7158ca0d 782 else if (packet == PUBREL_TYPE)
Azure.IoT Build 0:ef4901974abc 783 {
AzureIoTClient 3:9b4e7158ca0d 784 pubRel = mqtt_codec_publishComplete(publish_ack.packetId);
AzureIoTClient 5:34779607059c 785 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 786 {
AzureIoTClient 11:a0a6a4cf7812 787 LOG(AZ_LOG_ERROR, LOG_LINE, "Failed to allocate publish complete message.");
AzureIoTClient 9:37d14c31ff6e 788 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 5:34779607059c 789 }
Azure.IoT Build 0:ef4901974abc 790 }
Azure.IoT Build 0:ef4901974abc 791 if (pubRel != NULL)
Azure.IoT Build 0:ef4901974abc 792 {
AzureIoTClient 13:3c202001e4ba 793 size_t size = BUFFER_length(pubRel);
AzureIoTClient 13:3c202001e4ba 794 (void)sendPacketItem(mqtt_client, BUFFER_u_char(pubRel), size);
Azure.IoT Build 0:ef4901974abc 795 BUFFER_delete(pubRel);
Azure.IoT Build 0:ef4901974abc 796 }
Azure.IoT Build 0:ef4901974abc 797 }
AzureIoTClient 3:9b4e7158ca0d 798 break;
Azure.IoT Build 0:ef4901974abc 799 }
AzureIoTClient 3:9b4e7158ca0d 800 case SUBACK_TYPE:
Azure.IoT Build 0:ef4901974abc 801 {
AzureIoTClient 8:83bb166aba73 802 if (mqtt_client->fnOperationCallback)
AzureIoTClient 3:9b4e7158ca0d 803 {
AzureIoTClient 8:83bb166aba73 804 STRING_HANDLE trace_log = NULL;
AzureIoTClient 8:83bb166aba73 805
AzureIoTClient 3:9b4e7158ca0d 806 /*Codes_SRS_MQTT_CLIENT_07_030: [If the actionResult parameter is of type SUBACK_TYPE then the msgInfo value shall be a SUBSCRIBE_ACK structure.]*/
AzureIoTClient 3:9b4e7158ca0d 807 SUBSCRIBE_ACK suback = { 0 };
AzureIoTClient 3:9b4e7158ca0d 808
AzureIoTClient 3:9b4e7158ca0d 809 size_t remainLen = len;
AzureIoTClient 8:83bb166aba73 810 suback.packetId = byteutil_read_uint16(&iterator, len);
AzureIoTClient 3:9b4e7158ca0d 811 remainLen -= 2;
Azure.IoT Build 0:ef4901974abc 812
AzureIoTClient 8:83bb166aba73 813 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 814 {
AzureIoTClient 8:83bb166aba73 815 trace_log = STRING_construct_sprintf("SUBACK | PACKET_ID: %"PRIu16, suback.packetId);
AzureIoTClient 8:83bb166aba73 816 }
AzureIoTClient 8:83bb166aba73 817
AzureIoTClient 3:9b4e7158ca0d 818 // Allocate the remaining len
AzureIoTClient 3:9b4e7158ca0d 819 suback.qosReturn = (QOS_VALUE*)malloc(sizeof(QOS_VALUE)*remainLen);
AzureIoTClient 3:9b4e7158ca0d 820 if (suback.qosReturn != NULL)
Azure.IoT Build 0:ef4901974abc 821 {
AzureIoTClient 3:9b4e7158ca0d 822 while (remainLen > 0)
AzureIoTClient 3:9b4e7158ca0d 823 {
AzureIoTClient 28:35eea447689a 824 uint8_t qosRet = byteutil_readByte(&iterator);
AzureIoTClient 28:35eea447689a 825 suback.qosReturn[suback.qosCount++] =
AzureIoTClient 28:35eea447689a 826 (qosRet <= ((uint8_t)DELIVER_EXACTLY_ONCE)) ?
AzureIoTClient 28:35eea447689a 827 (QOS_VALUE)qosRet : DELIVER_FAILURE;
AzureIoTClient 3:9b4e7158ca0d 828 remainLen--;
AzureIoTClient 8:83bb166aba73 829 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 830 {
AzureIoTClient 8:83bb166aba73 831 STRING_sprintf(trace_log, " | RETURN_CODE: %"PRIu16, suback.qosReturn[suback.qosCount-1]);
AzureIoTClient 8:83bb166aba73 832 }
AzureIoTClient 3:9b4e7158ca0d 833 }
AzureIoTClient 8:83bb166aba73 834
AzureIoTClient 8:83bb166aba73 835 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 836 {
AzureIoTClient 8:83bb166aba73 837 log_incoming_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 838 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 839 }
AzureIoTClient 8:83bb166aba73 840 mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_SUBSCRIBE_ACK, (void*)&suback, mqtt_client->ctx);
AzureIoTClient 3:9b4e7158ca0d 841 free(suback.qosReturn);
Azure.IoT Build 0:ef4901974abc 842 }
AzureIoTClient 5:34779607059c 843 else
AzureIoTClient 5:34779607059c 844 {
AzureIoTClient 11:a0a6a4cf7812 845 LOG(AZ_LOG_ERROR, LOG_LINE, "allocation of quality of service value failed.");
AzureIoTClient 9:37d14c31ff6e 846 set_error_callback(mqtt_client, MQTT_CLIENT_MEMORY_ERROR);
AzureIoTClient 5:34779607059c 847 }
Azure.IoT Build 0:ef4901974abc 848 }
AzureIoTClient 3:9b4e7158ca0d 849 break;
Azure.IoT Build 0:ef4901974abc 850 }
AzureIoTClient 3:9b4e7158ca0d 851 case UNSUBACK_TYPE:
Azure.IoT Build 0:ef4901974abc 852 {
AzureIoTClient 8:83bb166aba73 853 if (mqtt_client->fnOperationCallback)
AzureIoTClient 3:9b4e7158ca0d 854 {
AzureIoTClient 8:83bb166aba73 855 STRING_HANDLE trace_log = NULL;
AzureIoTClient 8:83bb166aba73 856
AzureIoTClient 3:9b4e7158ca0d 857 /*Codes_SRS_MQTT_CLIENT_07_031: [If the actionResult parameter is of type UNSUBACK_TYPE then the msgInfo value shall be a UNSUBSCRIBE_ACK structure.]*/
AzureIoTClient 3:9b4e7158ca0d 858 UNSUBSCRIBE_ACK unsuback = { 0 };
AzureIoTClient 8:83bb166aba73 859 unsuback.packetId = byteutil_read_uint16(&iterator, len);
Azure.IoT Build 0:ef4901974abc 860
AzureIoTClient 8:83bb166aba73 861 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 862 {
AzureIoTClient 8:83bb166aba73 863 trace_log = STRING_construct_sprintf("UNSUBACK | PACKET_ID: %"PRIu16, unsuback.packetId);
AzureIoTClient 8:83bb166aba73 864 log_incoming_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 865 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 866 }
AzureIoTClient 8:83bb166aba73 867 mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_UNSUBSCRIBE_ACK, (void*)&unsuback, mqtt_client->ctx);
AzureIoTClient 3:9b4e7158ca0d 868 }
AzureIoTClient 3:9b4e7158ca0d 869 break;
Azure.IoT Build 0:ef4901974abc 870 }
AzureIoTClient 3:9b4e7158ca0d 871 case PINGRESP_TYPE:
AzureIoTClient 29:7bb0aae34648 872 if (mqtt_client != NULL)
AzureIoTClient 8:83bb166aba73 873 {
AzureIoTClient 29:7bb0aae34648 874 mqtt_client->timeSincePing = 0;
AzureIoTClient 29:7bb0aae34648 875 if (mqtt_client->logTrace)
AzureIoTClient 29:7bb0aae34648 876 {
AzureIoTClient 29:7bb0aae34648 877 STRING_HANDLE trace_log = STRING_construct_sprintf("PINGRESP");
AzureIoTClient 29:7bb0aae34648 878 log_incoming_trace(mqtt_client, trace_log);
AzureIoTClient 29:7bb0aae34648 879 STRING_delete(trace_log);
AzureIoTClient 29:7bb0aae34648 880 }
AzureIoTClient 29:7bb0aae34648 881 // Forward ping response to operation callback
AzureIoTClient 29:7bb0aae34648 882 if (mqtt_client->fnOperationCallback)
AzureIoTClient 29:7bb0aae34648 883 {
AzureIoTClient 29:7bb0aae34648 884 mqtt_client->fnOperationCallback(mqtt_client, MQTT_CLIENT_ON_PING_RESPONSE, NULL, mqtt_client->ctx);
AzureIoTClient 29:7bb0aae34648 885 }
AzureIoTClient 8:83bb166aba73 886 }
AzureIoTClient 29:7bb0aae34648 887 else
AzureIoTClient 18:6d13ad04e8a0 888 {
AzureIoTClient 29:7bb0aae34648 889 LOG(AZ_LOG_ERROR, LOG_LINE, "MQTT client value NULL");
AzureIoTClient 18:6d13ad04e8a0 890 }
AzureIoTClient 3:9b4e7158ca0d 891 break;
AzureIoTClient 3:9b4e7158ca0d 892 default:
AzureIoTClient 3:9b4e7158ca0d 893 break;
Azure.IoT Build 0:ef4901974abc 894 }
Azure.IoT Build 0:ef4901974abc 895 }
Azure.IoT Build 0:ef4901974abc 896 }
Azure.IoT Build 0:ef4901974abc 897 }
Azure.IoT Build 0:ef4901974abc 898
AzureIoTClient 9:37d14c31ff6e 899 MQTT_CLIENT_HANDLE mqtt_client_init(ON_MQTT_MESSAGE_RECV_CALLBACK msgRecv, ON_MQTT_OPERATION_CALLBACK opCallback, void* opCallbackCtx, ON_MQTT_ERROR_CALLBACK onErrorCallBack, void* errorCBCtx)
Azure.IoT Build 0:ef4901974abc 900 {
Azure.IoT Build 0:ef4901974abc 901 MQTT_CLIENT* result;
Azure.IoT Build 0:ef4901974abc 902 /*Codes_SRS_MQTT_CLIENT_07_001: [If the parameters ON_MQTT_MESSAGE_RECV_CALLBACK is NULL then mqttclient_init shall return NULL.]*/
Azure.IoT Build 0:ef4901974abc 903 if (msgRecv == NULL)
Azure.IoT Build 0:ef4901974abc 904 {
Azure.IoT Build 0:ef4901974abc 905 result = NULL;
Azure.IoT Build 0:ef4901974abc 906 }
Azure.IoT Build 0:ef4901974abc 907 else
Azure.IoT Build 0:ef4901974abc 908 {
Azure.IoT Build 0:ef4901974abc 909 result = malloc(sizeof(MQTT_CLIENT));
Azure.IoT Build 0:ef4901974abc 910 if (result == NULL)
Azure.IoT Build 0:ef4901974abc 911 {
Azure.IoT Build 0:ef4901974abc 912 /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
AzureIoTClient 11:a0a6a4cf7812 913 LOG(AZ_LOG_ERROR, LOG_LINE, "mqtt_client_init failure: Allocation Failure");
Azure.IoT Build 0:ef4901974abc 914 }
Azure.IoT Build 0:ef4901974abc 915 else
Azure.IoT Build 0:ef4901974abc 916 {
AzureIoTClient 19:e283dcf26037 917 memset(result, 0, sizeof(MQTT_CLIENT));
Azure.IoT Build 0:ef4901974abc 918 /*Codes_SRS_MQTT_CLIENT_07_003: [mqttclient_init shall allocate MQTTCLIENT_DATA_INSTANCE and return the MQTTCLIENT_HANDLE on success.]*/
Azure.IoT Build 0:ef4901974abc 919 result->packetState = UNKNOWN_TYPE;
Azure.IoT Build 0:ef4901974abc 920 result->fnOperationCallback = opCallback;
AzureIoTClient 9:37d14c31ff6e 921 result->ctx = opCallbackCtx;
Azure.IoT Build 0:ef4901974abc 922 result->fnMessageRecv = msgRecv;
AzureIoTClient 9:37d14c31ff6e 923 result->fnOnErrorCallBack = onErrorCallBack;
AzureIoTClient 9:37d14c31ff6e 924 result->errorCBCtx = errorCBCtx;
Azure.IoT Build 0:ef4901974abc 925 result->qosValue = DELIVER_AT_MOST_ONCE;
Azure.IoT Build 0:ef4901974abc 926 result->packetTickCntr = tickcounter_create();
AzureIoTClient 3:9b4e7158ca0d 927 result->maxPingRespTime = DEFAULT_MAX_PING_RESPONSE_TIME;
Azure.IoT Build 0:ef4901974abc 928 if (result->packetTickCntr == NULL)
Azure.IoT Build 0:ef4901974abc 929 {
Azure.IoT Build 0:ef4901974abc 930 /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
AzureIoTClient 11:a0a6a4cf7812 931 LOG(AZ_LOG_ERROR, LOG_LINE, "mqtt_client_init failure: tickcounter_create failure");
Azure.IoT Build 0:ef4901974abc 932 free(result);
Azure.IoT Build 0:ef4901974abc 933 result = NULL;
Azure.IoT Build 0:ef4901974abc 934 }
Azure.IoT Build 0:ef4901974abc 935 else
Azure.IoT Build 0:ef4901974abc 936 {
Azure.IoT Build 0:ef4901974abc 937 result->codec_handle = mqtt_codec_create(recvCompleteCallback, result);
Azure.IoT Build 0:ef4901974abc 938 if (result->codec_handle == NULL)
Azure.IoT Build 0:ef4901974abc 939 {
Azure.IoT Build 0:ef4901974abc 940 /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
AzureIoTClient 11:a0a6a4cf7812 941 LOG(AZ_LOG_ERROR, LOG_LINE, "mqtt_client_init failure: mqtt_codec_create failure");
Azure.IoT Build 0:ef4901974abc 942 tickcounter_destroy(result->packetTickCntr);
Azure.IoT Build 0:ef4901974abc 943 free(result);
Azure.IoT Build 0:ef4901974abc 944 result = NULL;
Azure.IoT Build 0:ef4901974abc 945 }
Azure.IoT Build 0:ef4901974abc 946 }
Azure.IoT Build 0:ef4901974abc 947 }
Azure.IoT Build 0:ef4901974abc 948 }
Azure.IoT Build 0:ef4901974abc 949 return result;
Azure.IoT Build 0:ef4901974abc 950 }
Azure.IoT Build 0:ef4901974abc 951
Azure.IoT Build 0:ef4901974abc 952 void mqtt_client_deinit(MQTT_CLIENT_HANDLE handle)
Azure.IoT Build 0:ef4901974abc 953 {
Azure.IoT Build 0:ef4901974abc 954 /*Codes_SRS_MQTT_CLIENT_07_004: [If the parameter handle is NULL then function mqtt_client_deinit shall do nothing.]*/
Azure.IoT Build 0:ef4901974abc 955 if (handle != NULL)
Azure.IoT Build 0:ef4901974abc 956 {
Azure.IoT Build 0:ef4901974abc 957 /*Codes_SRS_MQTT_CLIENT_07_005: [mqtt_client_deinit shall deallocate all memory allocated in this unit.]*/
AzureIoTClient 8:83bb166aba73 958 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 8:83bb166aba73 959 tickcounter_destroy(mqtt_client->packetTickCntr);
AzureIoTClient 8:83bb166aba73 960 mqtt_codec_destroy(mqtt_client->codec_handle);
AzureIoTClient 18:6d13ad04e8a0 961 clear_mqtt_options(mqtt_client);
AzureIoTClient 8:83bb166aba73 962 free(mqtt_client);
Azure.IoT Build 0:ef4901974abc 963 }
Azure.IoT Build 0:ef4901974abc 964 }
Azure.IoT Build 0:ef4901974abc 965
Azure.IoT Build 0:ef4901974abc 966 int mqtt_client_connect(MQTT_CLIENT_HANDLE handle, XIO_HANDLE xioHandle, MQTT_CLIENT_OPTIONS* mqttOptions)
Azure.IoT Build 0:ef4901974abc 967 {
Azure.IoT Build 0:ef4901974abc 968 int result;
Azure.IoT Build 0:ef4901974abc 969 /*SRS_MQTT_CLIENT_07_006: [If any of the parameters handle, ioHandle, or mqttOptions are NULL then mqtt_client_connect shall return a non-zero value.]*/
Azure.IoT Build 0:ef4901974abc 970 if (handle == NULL || mqttOptions == NULL)
Azure.IoT Build 0:ef4901974abc 971 {
AzureIoTClient 11:a0a6a4cf7812 972 LOG(AZ_LOG_ERROR, LOG_LINE, "mqtt_client_connect: NULL argument (handle = %p, mqttOptions = %p)", handle, mqttOptions);
AzureIoTClient 15:ec5a36121959 973 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 974 }
Azure.IoT Build 0:ef4901974abc 975 else
Azure.IoT Build 0:ef4901974abc 976 {
AzureIoTClient 8:83bb166aba73 977 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 978 if (xioHandle == NULL)
Azure.IoT Build 0:ef4901974abc 979 {
Azure.IoT Build 0:ef4901974abc 980 /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 981 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqttcodec_connect failed");
AzureIoTClient 15:ec5a36121959 982 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 983 }
Azure.IoT Build 0:ef4901974abc 984 else
Azure.IoT Build 0:ef4901974abc 985 {
AzureIoTClient 8:83bb166aba73 986 mqtt_client->xioHandle = xioHandle;
AzureIoTClient 8:83bb166aba73 987 mqtt_client->packetState = UNKNOWN_TYPE;
AzureIoTClient 8:83bb166aba73 988 mqtt_client->qosValue = mqttOptions->qualityOfServiceValue;
AzureIoTClient 8:83bb166aba73 989 mqtt_client->keepAliveInterval = mqttOptions->keepAliveInterval;
AzureIoTClient 8:83bb166aba73 990 mqtt_client->maxPingRespTime = (DEFAULT_MAX_PING_RESPONSE_TIME < mqttOptions->keepAliveInterval/2) ? DEFAULT_MAX_PING_RESPONSE_TIME : mqttOptions->keepAliveInterval/2;
AzureIoTClient 8:83bb166aba73 991 if (cloneMqttOptions(mqtt_client, mqttOptions) != 0)
Azure.IoT Build 0:ef4901974abc 992 {
AzureIoTClient 11:a0a6a4cf7812 993 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: Clone Mqtt Options failed");
AzureIoTClient 15:ec5a36121959 994 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 995 }
Azure.IoT Build 0:ef4901974abc 996 /*Codes_SRS_MQTT_CLIENT_07_008: [mqtt_client_connect shall open the XIO_HANDLE by calling into the xio_open interface.]*/
AzureIoTClient 8:83bb166aba73 997 else if (xio_open(xioHandle, onOpenComplete, mqtt_client, onBytesReceived, mqtt_client, onIoError, mqtt_client) != 0)
Azure.IoT Build 0:ef4901974abc 998 {
Azure.IoT Build 0:ef4901974abc 999 /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1000 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: io_open failed");
AzureIoTClient 15:ec5a36121959 1001 result = __FAILURE__;
AzureIoTClient 14:4b5b4dccfc8b 1002 // Remove cloned options
AzureIoTClient 14:4b5b4dccfc8b 1003 clear_mqtt_options(mqtt_client);
Azure.IoT Build 0:ef4901974abc 1004 }
Azure.IoT Build 0:ef4901974abc 1005 else
Azure.IoT Build 0:ef4901974abc 1006 {
Azure.IoT Build 0:ef4901974abc 1007 result = 0;
Azure.IoT Build 0:ef4901974abc 1008 }
Azure.IoT Build 0:ef4901974abc 1009 }
Azure.IoT Build 0:ef4901974abc 1010 }
Azure.IoT Build 0:ef4901974abc 1011 return result;
Azure.IoT Build 0:ef4901974abc 1012 }
Azure.IoT Build 0:ef4901974abc 1013
Azure.IoT Build 0:ef4901974abc 1014 int mqtt_client_publish(MQTT_CLIENT_HANDLE handle, MQTT_MESSAGE_HANDLE msgHandle)
Azure.IoT Build 0:ef4901974abc 1015 {
Azure.IoT Build 0:ef4901974abc 1016 int result;
AzureIoTClient 8:83bb166aba73 1017 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 8:83bb166aba73 1018 if (mqtt_client == NULL || msgHandle == NULL)
Azure.IoT Build 0:ef4901974abc 1019 {
Azure.IoT Build 0:ef4901974abc 1020 /*Codes_SRS_MQTT_CLIENT_07_019: [If one of the parameters handle or msgHandle is NULL then mqtt_client_publish shall return a non-zero value.]*/
AzureIoTClient 17:73ae81ce481d 1021 LogError("Invalid parameter specified mqtt_client: %p, msgHandle: %p", mqtt_client, msgHandle);
AzureIoTClient 15:ec5a36121959 1022 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1023 }
Azure.IoT Build 0:ef4901974abc 1024 else
Azure.IoT Build 0:ef4901974abc 1025 {
Azure.IoT Build 0:ef4901974abc 1026 /*Codes_SRS_MQTT_CLIENT_07_021: [mqtt_client_publish shall get the message information from the MQTT_MESSAGE_HANDLE.]*/
Azure.IoT Build 0:ef4901974abc 1027 const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
Azure.IoT Build 0:ef4901974abc 1028 if (payload == NULL)
Azure.IoT Build 0:ef4901974abc 1029 {
Azure.IoT Build 0:ef4901974abc 1030 /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1031 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqttmessage_getApplicationMsg failed");
AzureIoTClient 15:ec5a36121959 1032 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1033 }
Azure.IoT Build 0:ef4901974abc 1034 else
Azure.IoT Build 0:ef4901974abc 1035 {
AzureIoTClient 8:83bb166aba73 1036 STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
AzureIoTClient 8:83bb166aba73 1037
AzureIoTClient 13:3c202001e4ba 1038 QOS_VALUE qos = mqttmessage_getQosType(msgHandle);
AzureIoTClient 13:3c202001e4ba 1039 bool isDuplicate = mqttmessage_getIsDuplicateMsg(msgHandle);
AzureIoTClient 13:3c202001e4ba 1040 bool isRetained = mqttmessage_getIsRetained(msgHandle);
AzureIoTClient 13:3c202001e4ba 1041 uint16_t packetId = mqttmessage_getPacketId(msgHandle);
AzureIoTClient 13:3c202001e4ba 1042 const char* topicName = mqttmessage_getTopicName(msgHandle);
AzureIoTClient 13:3c202001e4ba 1043 BUFFER_HANDLE publishPacket = mqtt_codec_publish(qos, isDuplicate, isRetained, packetId, topicName, payload->message, payload->length, trace_log);
Azure.IoT Build 0:ef4901974abc 1044 if (publishPacket == NULL)
Azure.IoT Build 0:ef4901974abc 1045 {
Azure.IoT Build 0:ef4901974abc 1046 /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1047 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_codec_publish failed");
AzureIoTClient 15:ec5a36121959 1048 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1049 }
Azure.IoT Build 0:ef4901974abc 1050 else
Azure.IoT Build 0:ef4901974abc 1051 {
AzureIoTClient 8:83bb166aba73 1052 mqtt_client->packetState = PUBLISH_TYPE;
Azure.IoT Build 0:ef4901974abc 1053
Azure.IoT Build 0:ef4901974abc 1054 /*Codes_SRS_MQTT_CLIENT_07_022: [On success mqtt_client_publish shall send the MQTT SUBCRIBE packet to the endpoint.]*/
AzureIoTClient 13:3c202001e4ba 1055 size_t size = BUFFER_length(publishPacket);
AzureIoTClient 13:3c202001e4ba 1056 if (sendPacketItem(mqtt_client, BUFFER_u_char(publishPacket), size) != 0)
Azure.IoT Build 0:ef4901974abc 1057 {
Azure.IoT Build 0:ef4901974abc 1058 /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1059 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_publish send failed");
AzureIoTClient 15:ec5a36121959 1060 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1061 }
Azure.IoT Build 0:ef4901974abc 1062 else
Azure.IoT Build 0:ef4901974abc 1063 {
AzureIoTClient 8:83bb166aba73 1064 log_outgoing_trace(mqtt_client, trace_log);
Azure.IoT Build 0:ef4901974abc 1065 result = 0;
Azure.IoT Build 0:ef4901974abc 1066 }
Azure.IoT Build 0:ef4901974abc 1067 BUFFER_delete(publishPacket);
Azure.IoT Build 0:ef4901974abc 1068 }
AzureIoTClient 8:83bb166aba73 1069 if (trace_log != NULL)
AzureIoTClient 8:83bb166aba73 1070 {
AzureIoTClient 8:83bb166aba73 1071 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 1072 }
Azure.IoT Build 0:ef4901974abc 1073 }
Azure.IoT Build 0:ef4901974abc 1074 }
Azure.IoT Build 0:ef4901974abc 1075 return result;
Azure.IoT Build 0:ef4901974abc 1076 }
Azure.IoT Build 0:ef4901974abc 1077
Azure.IoT Build 0:ef4901974abc 1078 int mqtt_client_subscribe(MQTT_CLIENT_HANDLE handle, uint16_t packetId, SUBSCRIBE_PAYLOAD* subscribeList, size_t count)
Azure.IoT Build 0:ef4901974abc 1079 {
Azure.IoT Build 0:ef4901974abc 1080 int result;
AzureIoTClient 8:83bb166aba73 1081 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 17:73ae81ce481d 1082 if (mqtt_client == NULL || subscribeList == NULL || count == 0 || packetId == 0)
Azure.IoT Build 0:ef4901974abc 1083 {
Azure.IoT Build 0:ef4901974abc 1084 /*Codes_SRS_MQTT_CLIENT_07_013: [If any of the parameters handle, subscribeList is NULL or count is 0 then mqtt_client_subscribe shall return a non-zero value.]*/
AzureIoTClient 17:73ae81ce481d 1085 LogError("Invalid parameter specified mqtt_client: %p, subscribeList: %p, count: %d, packetId: %d", mqtt_client, subscribeList, count, packetId);
AzureIoTClient 15:ec5a36121959 1086 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1087 }
Azure.IoT Build 0:ef4901974abc 1088 else
Azure.IoT Build 0:ef4901974abc 1089 {
AzureIoTClient 8:83bb166aba73 1090 STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
AzureIoTClient 8:83bb166aba73 1091
AzureIoTClient 8:83bb166aba73 1092 BUFFER_HANDLE subPacket = mqtt_codec_subscribe(packetId, subscribeList, count, trace_log);
Azure.IoT Build 0:ef4901974abc 1093 if (subPacket == NULL)
Azure.IoT Build 0:ef4901974abc 1094 {
Azure.IoT Build 0:ef4901974abc 1095 /*Codes_SRS_MQTT_CLIENT_07_014: [If any failure is encountered then mqtt_client_subscribe shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1096 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_codec_subscribe failed");
AzureIoTClient 15:ec5a36121959 1097 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1098 }
Azure.IoT Build 0:ef4901974abc 1099 else
Azure.IoT Build 0:ef4901974abc 1100 {
AzureIoTClient 8:83bb166aba73 1101 mqtt_client->packetState = SUBSCRIBE_TYPE;
Azure.IoT Build 0:ef4901974abc 1102
AzureIoTClient 13:3c202001e4ba 1103 size_t size = BUFFER_length(subPacket);
Azure.IoT Build 0:ef4901974abc 1104 /*Codes_SRS_MQTT_CLIENT_07_015: [On success mqtt_client_subscribe shall send the MQTT SUBCRIBE packet to the endpoint.]*/
AzureIoTClient 13:3c202001e4ba 1105 if (sendPacketItem(mqtt_client, BUFFER_u_char(subPacket), size) != 0)
Azure.IoT Build 0:ef4901974abc 1106 {
Azure.IoT Build 0:ef4901974abc 1107 /*Codes_SRS_MQTT_CLIENT_07_014: [If any failure is encountered then mqtt_client_subscribe shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1108 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_subscribe send failed");
AzureIoTClient 15:ec5a36121959 1109 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1110 }
Azure.IoT Build 0:ef4901974abc 1111 else
Azure.IoT Build 0:ef4901974abc 1112 {
AzureIoTClient 8:83bb166aba73 1113 log_outgoing_trace(mqtt_client, trace_log);
Azure.IoT Build 0:ef4901974abc 1114 result = 0;
Azure.IoT Build 0:ef4901974abc 1115 }
Azure.IoT Build 0:ef4901974abc 1116 BUFFER_delete(subPacket);
Azure.IoT Build 0:ef4901974abc 1117 }
AzureIoTClient 8:83bb166aba73 1118 if (trace_log != NULL)
AzureIoTClient 8:83bb166aba73 1119 {
AzureIoTClient 8:83bb166aba73 1120 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 1121 }
Azure.IoT Build 0:ef4901974abc 1122 }
Azure.IoT Build 0:ef4901974abc 1123 return result;
Azure.IoT Build 0:ef4901974abc 1124 }
Azure.IoT Build 0:ef4901974abc 1125
Azure.IoT Build 0:ef4901974abc 1126 int mqtt_client_unsubscribe(MQTT_CLIENT_HANDLE handle, uint16_t packetId, const char** unsubscribeList, size_t count)
Azure.IoT Build 0:ef4901974abc 1127 {
Azure.IoT Build 0:ef4901974abc 1128 int result;
AzureIoTClient 8:83bb166aba73 1129 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 17:73ae81ce481d 1130 if (mqtt_client == NULL || unsubscribeList == NULL || count == 0 || packetId == 0)
Azure.IoT Build 0:ef4901974abc 1131 {
Azure.IoT Build 0:ef4901974abc 1132 /*Codes_SRS_MQTT_CLIENT_07_016: [If any of the parameters handle, unsubscribeList is NULL or count is 0 then mqtt_client_unsubscribe shall return a non-zero value.]*/
AzureIoTClient 17:73ae81ce481d 1133 LogError("Invalid parameter specified mqtt_client: %p, unsubscribeList: %p, count: %d, packetId: %d", mqtt_client, unsubscribeList, count, packetId);
AzureIoTClient 15:ec5a36121959 1134 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1135 }
Azure.IoT Build 0:ef4901974abc 1136 else
Azure.IoT Build 0:ef4901974abc 1137 {
AzureIoTClient 8:83bb166aba73 1138 STRING_HANDLE trace_log = construct_trace_log_handle(mqtt_client);
AzureIoTClient 8:83bb166aba73 1139
AzureIoTClient 8:83bb166aba73 1140 BUFFER_HANDLE unsubPacket = mqtt_codec_unsubscribe(packetId, unsubscribeList, count, trace_log);
Azure.IoT Build 0:ef4901974abc 1141 if (unsubPacket == NULL)
Azure.IoT Build 0:ef4901974abc 1142 {
Azure.IoT Build 0:ef4901974abc 1143 /*Codes_SRS_MQTT_CLIENT_07_017: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
AzureIoTClient 11:a0a6a4cf7812 1144 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_codec_unsubscribe failed");
AzureIoTClient 15:ec5a36121959 1145 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1146 }
Azure.IoT Build 0:ef4901974abc 1147 else
Azure.IoT Build 0:ef4901974abc 1148 {
AzureIoTClient 8:83bb166aba73 1149 mqtt_client->packetState = UNSUBSCRIBE_TYPE;
Azure.IoT Build 0:ef4901974abc 1150
AzureIoTClient 13:3c202001e4ba 1151 size_t size = BUFFER_length(unsubPacket);
Azure.IoT Build 0:ef4901974abc 1152 /*Codes_SRS_MQTT_CLIENT_07_018: [On success mqtt_client_unsubscribe shall send the MQTT SUBCRIBE packet to the endpoint.]*/
AzureIoTClient 13:3c202001e4ba 1153 if (sendPacketItem(mqtt_client, BUFFER_u_char(unsubPacket), size) != 0)
Azure.IoT Build 0:ef4901974abc 1154 {
Azure.IoT Build 0:ef4901974abc 1155 /*Codes_SRS_MQTT_CLIENT_07_017: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.].]*/
AzureIoTClient 11:a0a6a4cf7812 1156 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_unsubscribe send failed");
AzureIoTClient 15:ec5a36121959 1157 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1158 }
Azure.IoT Build 0:ef4901974abc 1159 else
Azure.IoT Build 0:ef4901974abc 1160 {
AzureIoTClient 8:83bb166aba73 1161 log_outgoing_trace(mqtt_client, trace_log);
Azure.IoT Build 0:ef4901974abc 1162 result = 0;
Azure.IoT Build 0:ef4901974abc 1163 }
Azure.IoT Build 0:ef4901974abc 1164 BUFFER_delete(unsubPacket);
Azure.IoT Build 0:ef4901974abc 1165 }
AzureIoTClient 8:83bb166aba73 1166 if (trace_log != NULL)
AzureIoTClient 8:83bb166aba73 1167 {
AzureIoTClient 8:83bb166aba73 1168 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 1169 }
Azure.IoT Build 0:ef4901974abc 1170 }
Azure.IoT Build 0:ef4901974abc 1171 return result;
Azure.IoT Build 0:ef4901974abc 1172 }
Azure.IoT Build 0:ef4901974abc 1173
AzureIoTClient 19:e283dcf26037 1174 int mqtt_client_disconnect(MQTT_CLIENT_HANDLE handle, ON_MQTT_DISCONNECTED_CALLBACK callback, void* ctx)
Azure.IoT Build 0:ef4901974abc 1175 {
Azure.IoT Build 0:ef4901974abc 1176 int result;
AzureIoTClient 8:83bb166aba73 1177 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 8:83bb166aba73 1178 if (mqtt_client == NULL)
Azure.IoT Build 0:ef4901974abc 1179 {
Azure.IoT Build 0:ef4901974abc 1180 /*Codes_SRS_MQTT_CLIENT_07_010: [If the parameters handle is NULL then mqtt_client_disconnect shall return a non-zero value.]*/
AzureIoTClient 15:ec5a36121959 1181 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1182 }
Azure.IoT Build 0:ef4901974abc 1183 else
Azure.IoT Build 0:ef4901974abc 1184 {
AzureIoTClient 23:80794cfb3565 1185 if (mqtt_client->clientConnected)
Azure.IoT Build 0:ef4901974abc 1186 {
AzureIoTClient 23:80794cfb3565 1187 BUFFER_HANDLE disconnectPacket = mqtt_codec_disconnect();
AzureIoTClient 23:80794cfb3565 1188 if (disconnectPacket == NULL)
Azure.IoT Build 0:ef4901974abc 1189 {
Azure.IoT Build 0:ef4901974abc 1190 /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
AzureIoTClient 23:80794cfb3565 1191 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect failed");
AzureIoTClient 23:80794cfb3565 1192 mqtt_client->packetState = PACKET_TYPE_ERROR;
AzureIoTClient 15:ec5a36121959 1193 result = __FAILURE__;
Azure.IoT Build 0:ef4901974abc 1194 }
Azure.IoT Build 0:ef4901974abc 1195 else
Azure.IoT Build 0:ef4901974abc 1196 {
AzureIoTClient 23:80794cfb3565 1197 /* Codes_SRS_MQTT_CLIENT_07_037: [ if callback is not NULL callback shall be called once the mqtt connection has been disconnected ] */
AzureIoTClient 23:80794cfb3565 1198 mqtt_client->disconnect_cb = callback;
AzureIoTClient 23:80794cfb3565 1199 mqtt_client->disconnect_ctx = ctx;
AzureIoTClient 23:80794cfb3565 1200 mqtt_client->packetState = DISCONNECT_TYPE;
AzureIoTClient 23:80794cfb3565 1201
AzureIoTClient 23:80794cfb3565 1202 size_t size = BUFFER_length(disconnectPacket);
AzureIoTClient 23:80794cfb3565 1203 /*Codes_SRS_MQTT_CLIENT_07_012: [On success mqtt_client_disconnect shall send the MQTT DISCONNECT packet to the endpoint.]*/
AzureIoTClient 23:80794cfb3565 1204 if (sendPacketItem(mqtt_client, BUFFER_u_char(disconnectPacket), size) != 0)
AzureIoTClient 8:83bb166aba73 1205 {
AzureIoTClient 23:80794cfb3565 1206 /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
AzureIoTClient 23:80794cfb3565 1207 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect send failed");
AzureIoTClient 23:80794cfb3565 1208 result = __FAILURE__;
AzureIoTClient 8:83bb166aba73 1209 }
AzureIoTClient 23:80794cfb3565 1210 else
AzureIoTClient 23:80794cfb3565 1211 {
AzureIoTClient 23:80794cfb3565 1212 if (mqtt_client->logTrace)
AzureIoTClient 23:80794cfb3565 1213 {
AzureIoTClient 23:80794cfb3565 1214 STRING_HANDLE trace_log = STRING_construct("DISCONNECT");
AzureIoTClient 23:80794cfb3565 1215 log_outgoing_trace(mqtt_client, trace_log);
AzureIoTClient 23:80794cfb3565 1216 STRING_delete(trace_log);
AzureIoTClient 23:80794cfb3565 1217 }
AzureIoTClient 23:80794cfb3565 1218 result = 0;
AzureIoTClient 23:80794cfb3565 1219 }
AzureIoTClient 23:80794cfb3565 1220 BUFFER_delete(disconnectPacket);
Azure.IoT Build 0:ef4901974abc 1221 }
AzureIoTClient 14:4b5b4dccfc8b 1222 clear_mqtt_options(mqtt_client);
AzureIoTClient 16:4e4835036f27 1223 mqtt_client->xioHandle = NULL;
Azure.IoT Build 0:ef4901974abc 1224 }
AzureIoTClient 23:80794cfb3565 1225 else
AzureIoTClient 23:80794cfb3565 1226 {
AzureIoTClient 23:80794cfb3565 1227 // If the client is not connected then just close the underlying socket
AzureIoTClient 23:80794cfb3565 1228 mqtt_client->disconnect_cb = callback;
AzureIoTClient 23:80794cfb3565 1229 mqtt_client->disconnect_ctx = ctx;
AzureIoTClient 23:80794cfb3565 1230
AzureIoTClient 23:80794cfb3565 1231 close_connection(mqtt_client);
AzureIoTClient 23:80794cfb3565 1232 clear_mqtt_options(mqtt_client);
AzureIoTClient 23:80794cfb3565 1233 result = 0;
AzureIoTClient 23:80794cfb3565 1234 }
Azure.IoT Build 0:ef4901974abc 1235 }
Azure.IoT Build 0:ef4901974abc 1236 return result;
Azure.IoT Build 0:ef4901974abc 1237 }
Azure.IoT Build 0:ef4901974abc 1238
Azure.IoT Build 0:ef4901974abc 1239 void mqtt_client_dowork(MQTT_CLIENT_HANDLE handle)
Azure.IoT Build 0:ef4901974abc 1240 {
AzureIoTClient 8:83bb166aba73 1241 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 16:4e4835036f27 1242 /*Codes_SRS_MQTT_CLIENT_18_001: [If the client is disconnected, mqtt_client_dowork shall do nothing.]*/
Azure.IoT Build 0:ef4901974abc 1243 /*Codes_SRS_MQTT_CLIENT_07_023: [If the parameter handle is NULL then mqtt_client_dowork shall do nothing.]*/
AzureIoTClient 16:4e4835036f27 1244 if (mqtt_client != NULL && mqtt_client->xioHandle != NULL)
Azure.IoT Build 0:ef4901974abc 1245 {
Azure.IoT Build 0:ef4901974abc 1246 /*Codes_SRS_MQTT_CLIENT_07_024: [mqtt_client_dowork shall call the xio_dowork function to complete operations.]*/
AzureIoTClient 8:83bb166aba73 1247 xio_dowork(mqtt_client->xioHandle);
Azure.IoT Build 0:ef4901974abc 1248
Azure.IoT Build 0:ef4901974abc 1249 /*Codes_SRS_MQTT_CLIENT_07_025: [mqtt_client_dowork shall retrieve the the last packet send value and ...]*/
AzureIoTClient 8:83bb166aba73 1250 if (mqtt_client->socketConnected && mqtt_client->clientConnected && mqtt_client->keepAliveInterval > 0)
Azure.IoT Build 0:ef4901974abc 1251 {
Azure.IoT.Build 10:2ab268507775 1252 tickcounter_ms_t current_ms;
AzureIoTClient 8:83bb166aba73 1253 if (tickcounter_get_current_ms(mqtt_client->packetTickCntr, &current_ms) != 0)
Azure.IoT Build 0:ef4901974abc 1254 {
AzureIoTClient 11:a0a6a4cf7812 1255 LOG(AZ_LOG_ERROR, LOG_LINE, "Error: tickcounter_get_current_ms failed");
Azure.IoT Build 0:ef4901974abc 1256 }
Azure.IoT Build 0:ef4901974abc 1257 else
Azure.IoT Build 0:ef4901974abc 1258 {
AzureIoTClient 9:37d14c31ff6e 1259 /* Codes_SRS_MQTT_CLIENT_07_035: [If the timeSincePing has expired past the maxPingRespTime then mqtt_client_dowork shall call the Error Callback function with the message MQTT_CLIENT_NO_PING_RESPONSE] */
AzureIoTClient 8:83bb166aba73 1260 if (mqtt_client->timeSincePing > 0 && ((current_ms - mqtt_client->timeSincePing)/1000) > mqtt_client->maxPingRespTime)
AzureIoTClient 3:9b4e7158ca0d 1261 {
AzureIoTClient 3:9b4e7158ca0d 1262 // We haven't gotten a ping response in the alloted time
AzureIoTClient 9:37d14c31ff6e 1263 set_error_callback(mqtt_client, MQTT_CLIENT_NO_PING_RESPONSE);
AzureIoTClient 8:83bb166aba73 1264 mqtt_client->timeSincePing = 0;
AzureIoTClient 8:83bb166aba73 1265 mqtt_client->packetSendTimeMs = 0;
AzureIoTClient 8:83bb166aba73 1266 mqtt_client->packetState = UNKNOWN_TYPE;
AzureIoTClient 3:9b4e7158ca0d 1267 }
AzureIoTClient 23:80794cfb3565 1268 else if (((current_ms - mqtt_client->packetSendTimeMs) / 1000) >= mqtt_client->keepAliveInterval)
Azure.IoT Build 0:ef4901974abc 1269 {
Azure.IoT Build 0:ef4901974abc 1270 /*Codes_SRS_MQTT_CLIENT_07_026: [if keepAliveInternal is > 0 and the send time is greater than the MQTT KeepAliveInterval then it shall construct an MQTT PINGREQ packet.]*/
Azure.IoT Build 0:ef4901974abc 1271 BUFFER_HANDLE pingPacket = mqtt_codec_ping();
Azure.IoT Build 0:ef4901974abc 1272 if (pingPacket != NULL)
Azure.IoT Build 0:ef4901974abc 1273 {
AzureIoTClient 13:3c202001e4ba 1274 size_t size = BUFFER_length(pingPacket);
AzureIoTClient 13:3c202001e4ba 1275 (void)sendPacketItem(mqtt_client, BUFFER_u_char(pingPacket), size);
Azure.IoT Build 0:ef4901974abc 1276 BUFFER_delete(pingPacket);
AzureIoTClient 8:83bb166aba73 1277 (void)tickcounter_get_current_ms(mqtt_client->packetTickCntr, &mqtt_client->timeSincePing);
AzureIoTClient 8:83bb166aba73 1278
AzureIoTClient 8:83bb166aba73 1279 if (mqtt_client->logTrace)
AzureIoTClient 8:83bb166aba73 1280 {
AzureIoTClient 8:83bb166aba73 1281 STRING_HANDLE trace_log = STRING_construct("PINGREQ");
AzureIoTClient 8:83bb166aba73 1282 log_outgoing_trace(mqtt_client, trace_log);
AzureIoTClient 8:83bb166aba73 1283 STRING_delete(trace_log);
AzureIoTClient 8:83bb166aba73 1284 }
Azure.IoT Build 0:ef4901974abc 1285 }
Azure.IoT Build 0:ef4901974abc 1286 }
Azure.IoT Build 0:ef4901974abc 1287 }
Azure.IoT Build 0:ef4901974abc 1288 }
Azure.IoT Build 0:ef4901974abc 1289 }
Azure.IoT Build 0:ef4901974abc 1290 }
Azure.IoT Build 0:ef4901974abc 1291
Azure.IoT Build 0:ef4901974abc 1292 void mqtt_client_set_trace(MQTT_CLIENT_HANDLE handle, bool traceOn, bool rawBytesOn)
Azure.IoT Build 0:ef4901974abc 1293 {
AzureIoTClient 8:83bb166aba73 1294 MQTT_CLIENT* mqtt_client = (MQTT_CLIENT*)handle;
AzureIoTClient 8:83bb166aba73 1295 if (mqtt_client != NULL)
Azure.IoT Build 0:ef4901974abc 1296 {
AzureIoTClient 8:83bb166aba73 1297 mqtt_client->logTrace = traceOn;
AzureIoTClient 8:83bb166aba73 1298 mqtt_client->rawBytesTrace = rawBytesOn;
Azure.IoT Build 0:ef4901974abc 1299 }
Azure.IoT Build 0:ef4901974abc 1300 }