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:
Fri Aug 12 10:04:24 2016 -0700
Revision:
6:d9c4702f91ca
Parent:
5:34779607059c
Child:
8:83bb166aba73
1.0.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>
Azure.IoT Build 0:ef4901974abc 5 #include "azure_c_shared_utility/gballoc.h"
Azure.IoT Build 0:ef4901974abc 6 #include "azure_c_shared_utility/platform.h"
Azure.IoT Build 0:ef4901974abc 7 #include "azure_c_shared_utility/tickcounter.h"
Azure.IoT Build 0:ef4901974abc 8 #include "azure_c_shared_utility/crt_abstractions.h"
Azure.IoT Build 4:e7167dabd6e4 9 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 0:ef4901974abc 10
Azure.IoT Build 0:ef4901974abc 11 #include "azure_umqtt_c/mqtt_client.h"
Azure.IoT Build 0:ef4901974abc 12 #include "azure_umqtt_c/mqtt_codec.h"
AzureIoTClient 1:8dba42ff9701 13 #include <time.h>
Azure.IoT Build 0:ef4901974abc 14
Azure.IoT Build 0:ef4901974abc 15 #define KEEP_ALIVE_BUFFER_SEC 10
Azure.IoT Build 0:ef4901974abc 16 #define VARIABLE_HEADER_OFFSET 2
Azure.IoT Build 0:ef4901974abc 17 #define RETAIN_FLAG_MASK 0x1
Azure.IoT Build 0:ef4901974abc 18 #define QOS_LEAST_ONCE_FLAG_MASK 0x2
Azure.IoT Build 0:ef4901974abc 19 #define QOS_EXACTLY_ONCE_FLAG_MASK 0x4
Azure.IoT Build 0:ef4901974abc 20 #define DUPLICATE_FLAG_MASK 0x8
Azure.IoT Build 0:ef4901974abc 21 #define CONNECT_PACKET_MASK 0xf0
AzureIoTClient 1:8dba42ff9701 22 #define TIME_MAX_BUFFER 16
AzureIoTClient 3:9b4e7158ca0d 23 #define DEFAULT_MAX_PING_RESPONSE_TIME 90
Azure.IoT Build 0:ef4901974abc 24
Azure.IoT Build 0:ef4901974abc 25 static const char* FORMAT_HEX_CHAR = "0x%02x ";
Azure.IoT Build 0:ef4901974abc 26
Azure.IoT Build 0:ef4901974abc 27 typedef struct MQTT_CLIENT_TAG
Azure.IoT Build 0:ef4901974abc 28 {
Azure.IoT Build 0:ef4901974abc 29 XIO_HANDLE xioHandle;
Azure.IoT Build 0:ef4901974abc 30 MQTTCODEC_HANDLE codec_handle;
Azure.IoT Build 0:ef4901974abc 31 CONTROL_PACKET_TYPE packetState;
Azure.IoT Build 0:ef4901974abc 32 TICK_COUNTER_HANDLE packetTickCntr;
Azure.IoT Build 0:ef4901974abc 33 uint64_t packetSendTimeMs;
Azure.IoT Build 0:ef4901974abc 34 ON_MQTT_OPERATION_CALLBACK fnOperationCallback;
Azure.IoT Build 0:ef4901974abc 35 ON_MQTT_MESSAGE_RECV_CALLBACK fnMessageRecv;
Azure.IoT Build 0:ef4901974abc 36 void* ctx;
Azure.IoT Build 0:ef4901974abc 37 QOS_VALUE qosValue;
Azure.IoT Build 0:ef4901974abc 38 uint16_t keepAliveInterval;
Azure.IoT Build 0:ef4901974abc 39 MQTT_CLIENT_OPTIONS mqttOptions;
Azure.IoT Build 0:ef4901974abc 40 bool clientConnected;
Azure.IoT Build 0:ef4901974abc 41 bool socketConnected;
Azure.IoT Build 0:ef4901974abc 42 bool logTrace;
Azure.IoT Build 0:ef4901974abc 43 bool rawBytesTrace;
AzureIoTClient 3:9b4e7158ca0d 44 uint64_t timeSincePing;
AzureIoTClient 3:9b4e7158ca0d 45 uint16_t maxPingRespTime;
Azure.IoT Build 0:ef4901974abc 46 } MQTT_CLIENT;
Azure.IoT Build 0:ef4901974abc 47
Azure.IoT Build 0:ef4901974abc 48 static uint16_t byteutil_read_uint16(uint8_t** buffer)
Azure.IoT Build 0:ef4901974abc 49 {
Azure.IoT Build 0:ef4901974abc 50 uint16_t result = 0;
Azure.IoT Build 0:ef4901974abc 51 if (buffer != NULL)
Azure.IoT Build 0:ef4901974abc 52 {
Azure.IoT Build 0:ef4901974abc 53 result = 256 * ((uint8_t)(**buffer)) + (uint8_t)(*(*buffer + 1));
Azure.IoT Build 0:ef4901974abc 54 *buffer += 2; // Move the ptr
Azure.IoT Build 0:ef4901974abc 55 }
Azure.IoT Build 0:ef4901974abc 56 return result;
Azure.IoT Build 0:ef4901974abc 57 }
Azure.IoT Build 0:ef4901974abc 58
Azure.IoT Build 0:ef4901974abc 59 static char* byteutil_readUTF(uint8_t** buffer, size_t* byteLen)
Azure.IoT Build 0:ef4901974abc 60 {
Azure.IoT Build 0:ef4901974abc 61 char* result = NULL;
Azure.IoT Build 0:ef4901974abc 62 if (buffer != NULL)
Azure.IoT Build 0:ef4901974abc 63 {
Azure.IoT Build 0:ef4901974abc 64 // Get the length of the string
Azure.IoT Build 0:ef4901974abc 65 int len = byteutil_read_uint16(buffer);
Azure.IoT Build 0:ef4901974abc 66 if (len > 0)
Azure.IoT Build 0:ef4901974abc 67 {
Azure.IoT Build 0:ef4901974abc 68 result = (char*)malloc(len + 1);
Azure.IoT Build 0:ef4901974abc 69 if (result != NULL)
Azure.IoT Build 0:ef4901974abc 70 {
Azure.IoT Build 0:ef4901974abc 71 (void)memcpy(result, *buffer, len);
Azure.IoT Build 0:ef4901974abc 72 result[len] = '\0';
Azure.IoT Build 0:ef4901974abc 73 *buffer += len;
Azure.IoT Build 0:ef4901974abc 74 if (byteLen != NULL)
Azure.IoT Build 0:ef4901974abc 75 {
Azure.IoT Build 0:ef4901974abc 76 *byteLen = len;
Azure.IoT Build 0:ef4901974abc 77 }
Azure.IoT Build 0:ef4901974abc 78 }
Azure.IoT Build 0:ef4901974abc 79 }
Azure.IoT Build 0:ef4901974abc 80 }
Azure.IoT Build 0:ef4901974abc 81 return result;
Azure.IoT Build 0:ef4901974abc 82 }
Azure.IoT Build 0:ef4901974abc 83
Azure.IoT Build 0:ef4901974abc 84 static uint8_t byteutil_readByte(uint8_t** buffer)
Azure.IoT Build 0:ef4901974abc 85 {
Azure.IoT Build 0:ef4901974abc 86 uint8_t result = 0;
Azure.IoT Build 0:ef4901974abc 87 if (buffer != NULL)
Azure.IoT Build 0:ef4901974abc 88 {
Azure.IoT Build 0:ef4901974abc 89 result = **buffer;
Azure.IoT Build 0:ef4901974abc 90 (*buffer)++;
Azure.IoT Build 0:ef4901974abc 91 }
Azure.IoT Build 0:ef4901974abc 92 return result;
Azure.IoT Build 0:ef4901974abc 93 }
Azure.IoT Build 0:ef4901974abc 94
Azure.IoT Build 0:ef4901974abc 95 static void sendComplete(void* context, IO_SEND_RESULT send_result)
Azure.IoT Build 0:ef4901974abc 96 {
Azure.IoT Build 0:ef4901974abc 97 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)context;
AzureIoTClient 5:34779607059c 98 if (mqttData != NULL && mqttData->fnOperationCallback != NULL && send_result == IO_SEND_OK)
Azure.IoT Build 0:ef4901974abc 99 {
Azure.IoT Build 0:ef4901974abc 100 if (mqttData->packetState == DISCONNECT_TYPE)
Azure.IoT Build 0:ef4901974abc 101 {
Azure.IoT Build 0:ef4901974abc 102 /*Codes_SRS_MQTT_CLIENT_07_032: [If the actionResult parameter is of type MQTT_CLIENT_ON_DISCONNECT or MQTT_CLIENT_ON_ERROR the the msgInfo value shall be NULL.]*/
Azure.IoT Build 0:ef4901974abc 103 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_DISCONNECT, NULL, mqttData->ctx);
Azure.IoT Build 0:ef4901974abc 104
Azure.IoT Build 0:ef4901974abc 105 // close the xio
AzureIoTClient 5:34779607059c 106 if (xio_close(mqttData->xioHandle, NULL, mqttData->ctx) != 0)
AzureIoTClient 5:34779607059c 107 {
AzureIoTClient 5:34779607059c 108 LOG(LOG_ERROR, LOG_LINE, "MQTT xio_close failed to return a successful result.");
AzureIoTClient 5:34779607059c 109 }
Azure.IoT Build 0:ef4901974abc 110 mqttData->socketConnected = false;
Azure.IoT Build 0:ef4901974abc 111 mqttData->clientConnected = false;
Azure.IoT Build 0:ef4901974abc 112 }
Azure.IoT Build 0:ef4901974abc 113 }
AzureIoTClient 5:34779607059c 114 else
AzureIoTClient 5:34779607059c 115 {
AzureIoTClient 5:34779607059c 116 LOG(LOG_ERROR, LOG_LINE, "MQTT Send Complete Failure");
AzureIoTClient 5:34779607059c 117 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 118 {
AzureIoTClient 5:34779607059c 119 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 120 }
AzureIoTClient 5:34779607059c 121 }
Azure.IoT Build 0:ef4901974abc 122 }
Azure.IoT Build 0:ef4901974abc 123
Azure.IoT Build 0:ef4901974abc 124 static const char* retrievePacketType(CONTROL_PACKET_TYPE packet)
Azure.IoT Build 0:ef4901974abc 125 {
Azure.IoT Build 0:ef4901974abc 126 switch (packet&CONNECT_PACKET_MASK)
Azure.IoT Build 0:ef4901974abc 127 {
Azure.IoT Build 0:ef4901974abc 128 case CONNECT_TYPE: return "CONNECT";
Azure.IoT Build 0:ef4901974abc 129 case CONNACK_TYPE: return "CONNACK";
Azure.IoT Build 0:ef4901974abc 130 case PUBLISH_TYPE: return "PUBLISH";
Azure.IoT Build 0:ef4901974abc 131 case PUBACK_TYPE: return "PUBACK";
Azure.IoT Build 0:ef4901974abc 132 case PUBREC_TYPE: return "PUBREC";
Azure.IoT Build 0:ef4901974abc 133 case PUBREL_TYPE: return "PUBREL";
Azure.IoT Build 0:ef4901974abc 134 case SUBSCRIBE_TYPE: return "SUBSCRIBE";
Azure.IoT Build 0:ef4901974abc 135 case SUBACK_TYPE: return "SUBACK";
Azure.IoT Build 0:ef4901974abc 136 case UNSUBSCRIBE_TYPE: return "UNSUBSCRIBE";
Azure.IoT Build 0:ef4901974abc 137 case UNSUBACK_TYPE: return "UNSUBACK";
Azure.IoT Build 0:ef4901974abc 138 case PINGREQ_TYPE: return "PINGREQ";
Azure.IoT Build 0:ef4901974abc 139 case PINGRESP_TYPE: return "PINGRESP";
Azure.IoT Build 0:ef4901974abc 140 case DISCONNECT_TYPE: return "DISCONNECT";
Azure.IoT Build 0:ef4901974abc 141 default:
Azure.IoT Build 0:ef4901974abc 142 case PACKET_TYPE_ERROR:
Azure.IoT Build 0:ef4901974abc 143 case UNKNOWN_TYPE:
Azure.IoT Build 0:ef4901974abc 144 return "UNKNOWN";
Azure.IoT Build 0:ef4901974abc 145 }
Azure.IoT Build 0:ef4901974abc 146 }
Azure.IoT Build 0:ef4901974abc 147
AzureIoTClient 1:8dba42ff9701 148 static void getLogTime(char* timeResult, size_t len)
AzureIoTClient 1:8dba42ff9701 149 {
AzureIoTClient 1:8dba42ff9701 150 if (timeResult != NULL)
AzureIoTClient 1:8dba42ff9701 151 {
AzureIoTClient 1:8dba42ff9701 152 time_t localTime = time(NULL);
AzureIoTClient 1:8dba42ff9701 153 struct tm* tmInfo = localtime(&localTime);
AzureIoTClient 1:8dba42ff9701 154 if (strftime(timeResult, len, "%H:%M:%S", tmInfo) == 0)
AzureIoTClient 1:8dba42ff9701 155 {
AzureIoTClient 1:8dba42ff9701 156 timeResult[0] = '\0';
AzureIoTClient 1:8dba42ff9701 157 }
AzureIoTClient 1:8dba42ff9701 158 }
AzureIoTClient 1:8dba42ff9701 159 }
AzureIoTClient 1:8dba42ff9701 160
Azure.IoT Build 0:ef4901974abc 161 static void logOutgoingingMsgTrace(MQTT_CLIENT* clientData, const uint8_t* data, size_t length)
Azure.IoT Build 0:ef4901974abc 162 {
Azure.IoT Build 0:ef4901974abc 163 if (clientData != NULL && data != NULL && length > 0 && clientData->logTrace)
Azure.IoT Build 0:ef4901974abc 164 {
AzureIoTClient 1:8dba42ff9701 165 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 1:8dba42ff9701 166 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 1:8dba42ff9701 167
Azure.IoT Build 4:e7167dabd6e4 168 LOG(LOG_TRACE, 0, "-> %s %s: ", tmBuffer, retrievePacketType((unsigned char)data[0]));
Azure.IoT Build 0:ef4901974abc 169 for (size_t index = 0; index < length; index++)
Azure.IoT Build 0:ef4901974abc 170 {
Azure.IoT Build 4:e7167dabd6e4 171 LOG(LOG_TRACE, 0, (char*)FORMAT_HEX_CHAR, data[index]);
Azure.IoT Build 0:ef4901974abc 172 }
Azure.IoT Build 4:e7167dabd6e4 173
Azure.IoT Build 4:e7167dabd6e4 174 LOG(LOG_TRACE, LOG_LINE, "");
Azure.IoT Build 0:ef4901974abc 175 }
Azure.IoT Build 0:ef4901974abc 176 }
Azure.IoT Build 0:ef4901974abc 177
Azure.IoT Build 0:ef4901974abc 178 static void logIncomingMsgTrace(MQTT_CLIENT* clientData, CONTROL_PACKET_TYPE packet, int flags, const uint8_t* data, size_t length)
Azure.IoT Build 0:ef4901974abc 179 {
AzureIoTClient 6:d9c4702f91ca 180 #ifdef NO_LOGGING
AzureIoTClient 6:d9c4702f91ca 181 UNUSED(flags);
AzureIoTClient 6:d9c4702f91ca 182 #endif
AzureIoTClient 3:9b4e7158ca0d 183 if (clientData != NULL && clientData->logTrace)
Azure.IoT Build 0:ef4901974abc 184 {
AzureIoTClient 3:9b4e7158ca0d 185 if (data != NULL && length > 0)
AzureIoTClient 3:9b4e7158ca0d 186 {
AzureIoTClient 3:9b4e7158ca0d 187 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 3:9b4e7158ca0d 188 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 1:8dba42ff9701 189
Azure.IoT Build 4:e7167dabd6e4 190 LOG(LOG_TRACE, 0, "<- %s %s: 0x%02x 0x%02x ", tmBuffer, retrievePacketType((CONTROL_PACKET_TYPE)packet), (unsigned char)(packet | flags), length);
AzureIoTClient 3:9b4e7158ca0d 191 for (size_t index = 0; index < length; index++)
AzureIoTClient 3:9b4e7158ca0d 192 {
Azure.IoT Build 4:e7167dabd6e4 193 LOG(LOG_TRACE, 0, (char*)FORMAT_HEX_CHAR, data[index]);
AzureIoTClient 3:9b4e7158ca0d 194 }
Azure.IoT Build 4:e7167dabd6e4 195
Azure.IoT Build 4:e7167dabd6e4 196 LOG(LOG_TRACE, LOG_LINE, "");
AzureIoTClient 3:9b4e7158ca0d 197 }
AzureIoTClient 3:9b4e7158ca0d 198 else if (packet == PINGRESP_TYPE)
Azure.IoT Build 0:ef4901974abc 199 {
AzureIoTClient 3:9b4e7158ca0d 200 char tmBuffer[TIME_MAX_BUFFER];
AzureIoTClient 3:9b4e7158ca0d 201 getLogTime(tmBuffer, TIME_MAX_BUFFER);
AzureIoTClient 3:9b4e7158ca0d 202
Azure.IoT Build 4:e7167dabd6e4 203 LOG(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 204 }
Azure.IoT Build 0:ef4901974abc 205 }
Azure.IoT Build 0:ef4901974abc 206 }
Azure.IoT Build 0:ef4901974abc 207
Azure.IoT Build 4:e7167dabd6e4 208 static int sendPacketItem(MQTT_CLIENT* clientData, const unsigned char* data, size_t length)
Azure.IoT Build 0:ef4901974abc 209 {
Azure.IoT Build 0:ef4901974abc 210 int result;
Azure.IoT Build 0:ef4901974abc 211
Azure.IoT Build 0:ef4901974abc 212 if (tickcounter_get_current_ms(clientData->packetTickCntr, &clientData->packetSendTimeMs) != 0)
Azure.IoT Build 0:ef4901974abc 213 {
Azure.IoT Build 4:e7167dabd6e4 214 LOG(LOG_ERROR, LOG_LINE, "Failure getting current ms tickcounter");
Azure.IoT Build 0:ef4901974abc 215 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 216 }
Azure.IoT Build 0:ef4901974abc 217 else
Azure.IoT Build 0:ef4901974abc 218 {
Azure.IoT Build 4:e7167dabd6e4 219 result = xio_send(clientData->xioHandle, (const void*)data, length, sendComplete, clientData);
Azure.IoT Build 0:ef4901974abc 220 if (result != 0)
Azure.IoT Build 0:ef4901974abc 221 {
Azure.IoT Build 4:e7167dabd6e4 222 LOG(LOG_ERROR, LOG_LINE, "%d: Failure sending control packet data", result);
Azure.IoT Build 0:ef4901974abc 223 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 224 }
Azure.IoT Build 4:e7167dabd6e4 225 else
Azure.IoT Build 4:e7167dabd6e4 226 {
Azure.IoT Build 4:e7167dabd6e4 227 logOutgoingingMsgTrace(clientData, (const uint8_t*)data, length);
Azure.IoT Build 4:e7167dabd6e4 228 }
Azure.IoT Build 0:ef4901974abc 229 }
Azure.IoT Build 0:ef4901974abc 230 return result;
Azure.IoT Build 0:ef4901974abc 231 }
Azure.IoT Build 0:ef4901974abc 232
Azure.IoT Build 0:ef4901974abc 233 static void onOpenComplete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 0:ef4901974abc 234 {
Azure.IoT Build 0:ef4901974abc 235 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)context;
Azure.IoT Build 0:ef4901974abc 236 if (mqttData != NULL)
Azure.IoT Build 0:ef4901974abc 237 {
Azure.IoT Build 0:ef4901974abc 238 if (open_result == IO_OPEN_OK && !mqttData->socketConnected)
Azure.IoT Build 0:ef4901974abc 239 {
Azure.IoT Build 0:ef4901974abc 240 mqttData->packetState = CONNECT_TYPE;
Azure.IoT Build 0:ef4901974abc 241 mqttData->socketConnected = true;
Azure.IoT Build 0:ef4901974abc 242 // Send the Connect packet
Azure.IoT Build 0:ef4901974abc 243 BUFFER_HANDLE connPacket = mqtt_codec_connect(&mqttData->mqttOptions);
Azure.IoT Build 0:ef4901974abc 244 if (connPacket == NULL)
Azure.IoT Build 0:ef4901974abc 245 {
Azure.IoT Build 0:ef4901974abc 246 /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 247 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_codec_connect failed");
Azure.IoT Build 0:ef4901974abc 248 }
Azure.IoT Build 0:ef4901974abc 249 else
Azure.IoT Build 0:ef4901974abc 250 {
Azure.IoT Build 0:ef4901974abc 251 /*Codes_SRS_MQTT_CLIENT_07_009: [On success mqtt_client_connect shall send the MQTT CONNECT to the endpoint.]*/
Azure.IoT Build 0:ef4901974abc 252 if (sendPacketItem(mqttData, BUFFER_u_char(connPacket), BUFFER_length(connPacket)) != 0)
Azure.IoT Build 0:ef4901974abc 253 {
Azure.IoT Build 0:ef4901974abc 254 /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 255 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_codec_connect failed");
Azure.IoT Build 0:ef4901974abc 256 }
Azure.IoT Build 0:ef4901974abc 257 BUFFER_delete(connPacket);
Azure.IoT Build 0:ef4901974abc 258 }
Azure.IoT Build 0:ef4901974abc 259 }
Azure.IoT Build 0:ef4901974abc 260 else if (open_result == IO_OPEN_ERROR)
Azure.IoT Build 0:ef4901974abc 261 {
AzureIoTClient 5:34779607059c 262 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
Azure.IoT Build 0:ef4901974abc 263 }
Azure.IoT Build 0:ef4901974abc 264 }
Azure.IoT Build 0:ef4901974abc 265 }
Azure.IoT Build 0:ef4901974abc 266
Azure.IoT Build 0:ef4901974abc 267 static void onBytesReceived(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 0:ef4901974abc 268 {
Azure.IoT Build 0:ef4901974abc 269 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)context;
Azure.IoT Build 0:ef4901974abc 270 if (mqttData != NULL)
Azure.IoT Build 0:ef4901974abc 271 {
Azure.IoT Build 0:ef4901974abc 272 if (mqtt_codec_bytesReceived(mqttData->codec_handle, buffer, size) != 0)
Azure.IoT Build 0:ef4901974abc 273 {
Azure.IoT Build 0:ef4901974abc 274 if (mqttData->fnOperationCallback)
Azure.IoT Build 0:ef4901974abc 275 {
Azure.IoT Build 0:ef4901974abc 276 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
Azure.IoT Build 0:ef4901974abc 277 }
Azure.IoT Build 0:ef4901974abc 278 }
Azure.IoT Build 0:ef4901974abc 279 }
Azure.IoT Build 0:ef4901974abc 280 }
Azure.IoT Build 0:ef4901974abc 281
Azure.IoT Build 0:ef4901974abc 282 static void onIoError(void* context)
Azure.IoT Build 0:ef4901974abc 283 {
Azure.IoT Build 0:ef4901974abc 284 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)context;
Azure.IoT Build 0:ef4901974abc 285 if (mqttData != NULL && mqttData->fnOperationCallback)
Azure.IoT Build 0:ef4901974abc 286 {
Azure.IoT Build 0:ef4901974abc 287 /*Codes_SRS_MQTT_CLIENT_07_032: [If the actionResult parameter is of type MQTT_CLIENT_ON_DISCONNECT or MQTT_CLIENT_ON_ERROR the the msgInfo value shall be NULL.]*/
Azure.IoT Build 0:ef4901974abc 288 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
Azure.IoT Build 0:ef4901974abc 289 mqttData->socketConnected = false;
Azure.IoT Build 0:ef4901974abc 290 }
Azure.IoT Build 0:ef4901974abc 291 }
Azure.IoT Build 0:ef4901974abc 292
Azure.IoT Build 0:ef4901974abc 293 static int cloneMqttOptions(MQTT_CLIENT* mqttData, const MQTT_CLIENT_OPTIONS* mqttOptions)
Azure.IoT Build 0:ef4901974abc 294 {
Azure.IoT Build 0:ef4901974abc 295 int result = 0;
Azure.IoT Build 0:ef4901974abc 296 if (mqttOptions->clientId != NULL)
Azure.IoT Build 0:ef4901974abc 297 {
Azure.IoT Build 0:ef4901974abc 298 if (mallocAndStrcpy_s(&mqttData->mqttOptions.clientId, mqttOptions->clientId) != 0)
Azure.IoT Build 0:ef4901974abc 299 {
Azure.IoT Build 0:ef4901974abc 300 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 301 }
Azure.IoT Build 0:ef4901974abc 302 }
Azure.IoT Build 0:ef4901974abc 303 if (result == 0 && mqttOptions->willTopic != NULL)
Azure.IoT Build 0:ef4901974abc 304 {
Azure.IoT Build 0:ef4901974abc 305 if (mallocAndStrcpy_s(&mqttData->mqttOptions.willTopic, mqttOptions->willTopic) != 0)
Azure.IoT Build 0:ef4901974abc 306 {
Azure.IoT Build 0:ef4901974abc 307 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 308 }
Azure.IoT Build 0:ef4901974abc 309 }
Azure.IoT Build 0:ef4901974abc 310 if (result == 0 && mqttOptions->willMessage != NULL)
Azure.IoT Build 0:ef4901974abc 311 {
Azure.IoT Build 0:ef4901974abc 312 if (mallocAndStrcpy_s(&mqttData->mqttOptions.willMessage, mqttOptions->willMessage) != 0)
Azure.IoT Build 0:ef4901974abc 313 {
Azure.IoT Build 0:ef4901974abc 314 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 315 }
Azure.IoT Build 0:ef4901974abc 316 }
Azure.IoT Build 0:ef4901974abc 317 if (result == 0 && mqttOptions->username != NULL)
Azure.IoT Build 0:ef4901974abc 318 {
Azure.IoT Build 0:ef4901974abc 319 if (mallocAndStrcpy_s(&mqttData->mqttOptions.username, mqttOptions->username) != 0)
Azure.IoT Build 0:ef4901974abc 320 {
Azure.IoT Build 0:ef4901974abc 321 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 322 }
Azure.IoT Build 0:ef4901974abc 323 }
Azure.IoT Build 0:ef4901974abc 324 if (result == 0 && mqttOptions->password != NULL)
Azure.IoT Build 0:ef4901974abc 325 {
Azure.IoT Build 0:ef4901974abc 326 if (mallocAndStrcpy_s(&mqttData->mqttOptions.password, mqttOptions->password) != 0)
Azure.IoT Build 0:ef4901974abc 327 {
Azure.IoT Build 0:ef4901974abc 328 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 329 }
Azure.IoT Build 0:ef4901974abc 330 }
Azure.IoT Build 0:ef4901974abc 331 if (result == 0)
Azure.IoT Build 0:ef4901974abc 332 {
Azure.IoT Build 0:ef4901974abc 333 mqttData->mqttOptions.keepAliveInterval = mqttOptions->keepAliveInterval;
Azure.IoT Build 0:ef4901974abc 334 mqttData->mqttOptions.messageRetain = mqttOptions->messageRetain;
Azure.IoT Build 0:ef4901974abc 335 mqttData->mqttOptions.useCleanSession = mqttOptions->useCleanSession;
Azure.IoT Build 0:ef4901974abc 336 mqttData->mqttOptions.qualityOfServiceValue = mqttOptions->qualityOfServiceValue;
Azure.IoT Build 0:ef4901974abc 337 }
Azure.IoT Build 0:ef4901974abc 338 else
Azure.IoT Build 0:ef4901974abc 339 {
Azure.IoT Build 0:ef4901974abc 340 free(mqttData->mqttOptions.clientId);
Azure.IoT Build 0:ef4901974abc 341 free(mqttData->mqttOptions.willTopic);
Azure.IoT Build 0:ef4901974abc 342 free(mqttData->mqttOptions.willMessage);
Azure.IoT Build 0:ef4901974abc 343 free(mqttData->mqttOptions.username);
Azure.IoT Build 0:ef4901974abc 344 free(mqttData->mqttOptions.password);
Azure.IoT Build 0:ef4901974abc 345 }
Azure.IoT Build 0:ef4901974abc 346 return result;
Azure.IoT Build 0:ef4901974abc 347 }
Azure.IoT Build 0:ef4901974abc 348
Azure.IoT Build 0:ef4901974abc 349 static void recvCompleteCallback(void* context, CONTROL_PACKET_TYPE packet, int flags, BUFFER_HANDLE headerData)
Azure.IoT Build 0:ef4901974abc 350 {
Azure.IoT Build 0:ef4901974abc 351 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)context;
AzureIoTClient 3:9b4e7158ca0d 352 if ((mqttData != NULL && headerData != NULL) || packet == PINGRESP_TYPE)
Azure.IoT Build 0:ef4901974abc 353 {
Azure.IoT Build 0:ef4901974abc 354 size_t len = BUFFER_length(headerData);
Azure.IoT Build 0:ef4901974abc 355 uint8_t* iterator = BUFFER_u_char(headerData);
Azure.IoT Build 0:ef4901974abc 356
Azure.IoT Build 0:ef4901974abc 357 logIncomingMsgTrace(mqttData, packet, flags, iterator, len);
Azure.IoT Build 0:ef4901974abc 358
AzureIoTClient 3:9b4e7158ca0d 359 if ((iterator != NULL && len > 0) || packet == PINGRESP_TYPE)
Azure.IoT Build 0:ef4901974abc 360 {
Azure.IoT Build 0:ef4901974abc 361 switch (packet)
Azure.IoT Build 0:ef4901974abc 362 {
AzureIoTClient 3:9b4e7158ca0d 363 case CONNACK_TYPE:
Azure.IoT Build 0:ef4901974abc 364 {
AzureIoTClient 3:9b4e7158ca0d 365 if (mqttData->fnOperationCallback != NULL)
AzureIoTClient 3:9b4e7158ca0d 366 {
AzureIoTClient 3:9b4e7158ca0d 367 /*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 368 CONNECT_ACK connack = { 0 };
AzureIoTClient 3:9b4e7158ca0d 369 connack.isSessionPresent = (byteutil_readByte(&iterator) == 0x1) ? true : false;
AzureIoTClient 3:9b4e7158ca0d 370 connack.returnCode = byteutil_readByte(&iterator);
Azure.IoT Build 0:ef4901974abc 371
AzureIoTClient 3:9b4e7158ca0d 372 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_CONNACK, (void*)&connack, mqttData->ctx);
AzureIoTClient 3:9b4e7158ca0d 373
AzureIoTClient 3:9b4e7158ca0d 374 if (connack.returnCode == CONNECTION_ACCEPTED)
AzureIoTClient 3:9b4e7158ca0d 375 {
AzureIoTClient 3:9b4e7158ca0d 376 mqttData->clientConnected = true;
AzureIoTClient 3:9b4e7158ca0d 377 }
Azure.IoT Build 0:ef4901974abc 378 }
AzureIoTClient 3:9b4e7158ca0d 379 break;
Azure.IoT Build 0:ef4901974abc 380 }
AzureIoTClient 3:9b4e7158ca0d 381 case PUBLISH_TYPE:
Azure.IoT Build 0:ef4901974abc 382 {
AzureIoTClient 3:9b4e7158ca0d 383 if (mqttData->fnMessageRecv != NULL)
AzureIoTClient 3:9b4e7158ca0d 384 {
AzureIoTClient 3:9b4e7158ca0d 385 bool isDuplicateMsg = (flags & DUPLICATE_FLAG_MASK) ? true : false;
AzureIoTClient 3:9b4e7158ca0d 386 bool isRetainMsg = (flags & RETAIN_FLAG_MASK) ? true : false;
AzureIoTClient 3:9b4e7158ca0d 387 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 388
AzureIoTClient 3:9b4e7158ca0d 389 uint8_t* initialPos = iterator;
AzureIoTClient 3:9b4e7158ca0d 390 char* topicName = byteutil_readUTF(&iterator, NULL);
AzureIoTClient 5:34779607059c 391 if (topicName == NULL)
AzureIoTClient 3:9b4e7158ca0d 392 {
AzureIoTClient 5:34779607059c 393 LOG(LOG_ERROR, LOG_LINE, "Publish MSG: failure reading topic name");
AzureIoTClient 5:34779607059c 394 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 395 {
AzureIoTClient 5:34779607059c 396 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 397 }
AzureIoTClient 3:9b4e7158ca0d 398 }
AzureIoTClient 3:9b4e7158ca0d 399 else
AzureIoTClient 3:9b4e7158ca0d 400 {
AzureIoTClient 5:34779607059c 401 uint16_t packetId = 0;
AzureIoTClient 5:34779607059c 402 if (qosValue != DELIVER_AT_MOST_ONCE)
AzureIoTClient 5:34779607059c 403 {
AzureIoTClient 5:34779607059c 404 packetId = byteutil_read_uint16(&iterator);
AzureIoTClient 5:34779607059c 405 }
AzureIoTClient 5:34779607059c 406 size_t length = len - (iterator - initialPos);
AzureIoTClient 3:9b4e7158ca0d 407
AzureIoTClient 5:34779607059c 408 MQTT_MESSAGE_HANDLE msgHandle = mqttmessage_create(packetId, topicName, qosValue, iterator, length);
AzureIoTClient 5:34779607059c 409 if (msgHandle == NULL)
AzureIoTClient 3:9b4e7158ca0d 410 {
AzureIoTClient 5:34779607059c 411 LOG(LOG_ERROR, LOG_LINE, "failure in mqttmessage_create");
AzureIoTClient 5:34779607059c 412 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 413 {
AzureIoTClient 5:34779607059c 414 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 415 }
AzureIoTClient 3:9b4e7158ca0d 416 }
AzureIoTClient 5:34779607059c 417 else
AzureIoTClient 3:9b4e7158ca0d 418 {
AzureIoTClient 5:34779607059c 419 if (mqttmessage_setIsDuplicateMsg(msgHandle, isDuplicateMsg) != 0 ||
AzureIoTClient 5:34779607059c 420 mqttmessage_setIsRetained(msgHandle, isRetainMsg) != 0)
AzureIoTClient 5:34779607059c 421 {
AzureIoTClient 5:34779607059c 422 LOG(LOG_ERROR, LOG_LINE, "failure setting mqtt message property");
AzureIoTClient 5:34779607059c 423 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 424 {
AzureIoTClient 5:34779607059c 425 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 426 }
AzureIoTClient 5:34779607059c 427 }
AzureIoTClient 5:34779607059c 428 else
AzureIoTClient 5:34779607059c 429 {
AzureIoTClient 5:34779607059c 430 mqttData->fnMessageRecv(msgHandle, mqttData->ctx);
AzureIoTClient 5:34779607059c 431
AzureIoTClient 5:34779607059c 432 BUFFER_HANDLE pubRel = NULL;
AzureIoTClient 5:34779607059c 433 if (qosValue == DELIVER_EXACTLY_ONCE)
AzureIoTClient 5:34779607059c 434 {
AzureIoTClient 5:34779607059c 435 pubRel = mqtt_codec_publishReceived(packetId);
AzureIoTClient 5:34779607059c 436 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 437 {
AzureIoTClient 5:34779607059c 438 LOG(LOG_ERROR, LOG_LINE, "Failed to allocate publish receive message.");
AzureIoTClient 5:34779607059c 439 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 440 {
AzureIoTClient 5:34779607059c 441 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 442 }
AzureIoTClient 5:34779607059c 443 }
AzureIoTClient 5:34779607059c 444 }
AzureIoTClient 5:34779607059c 445 else if (qosValue == DELIVER_AT_LEAST_ONCE)
AzureIoTClient 5:34779607059c 446 {
AzureIoTClient 5:34779607059c 447 pubRel = mqtt_codec_publishAck(packetId);
AzureIoTClient 5:34779607059c 448 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 449 {
AzureIoTClient 5:34779607059c 450 LOG(LOG_ERROR, LOG_LINE, "Failed to allocate publish ack message.");
AzureIoTClient 5:34779607059c 451 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 452 {
AzureIoTClient 5:34779607059c 453 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 454 }
AzureIoTClient 5:34779607059c 455 }
AzureIoTClient 5:34779607059c 456 }
AzureIoTClient 5:34779607059c 457 if (pubRel != NULL)
AzureIoTClient 5:34779607059c 458 {
AzureIoTClient 5:34779607059c 459 (void)sendPacketItem(mqttData, BUFFER_u_char(pubRel), BUFFER_length(pubRel));
AzureIoTClient 5:34779607059c 460 BUFFER_delete(pubRel);
AzureIoTClient 5:34779607059c 461 }
AzureIoTClient 5:34779607059c 462 }
AzureIoTClient 5:34779607059c 463 mqttmessage_destroy(msgHandle);
AzureIoTClient 3:9b4e7158ca0d 464 }
AzureIoTClient 3:9b4e7158ca0d 465 free(topicName);
AzureIoTClient 3:9b4e7158ca0d 466 }
Azure.IoT Build 0:ef4901974abc 467 }
AzureIoTClient 3:9b4e7158ca0d 468 break;
AzureIoTClient 3:9b4e7158ca0d 469 }
AzureIoTClient 3:9b4e7158ca0d 470 case PUBACK_TYPE:
AzureIoTClient 3:9b4e7158ca0d 471 case PUBREC_TYPE:
AzureIoTClient 3:9b4e7158ca0d 472 case PUBREL_TYPE:
AzureIoTClient 3:9b4e7158ca0d 473 case PUBCOMP_TYPE:
AzureIoTClient 3:9b4e7158ca0d 474 {
AzureIoTClient 3:9b4e7158ca0d 475 if (mqttData->fnOperationCallback)
Azure.IoT Build 0:ef4901974abc 476 {
AzureIoTClient 3:9b4e7158ca0d 477 /*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 478 MQTT_CLIENT_EVENT_RESULT action = (packet == PUBACK_TYPE) ? MQTT_CLIENT_ON_PUBLISH_ACK :
AzureIoTClient 3:9b4e7158ca0d 479 (packet == PUBREC_TYPE) ? MQTT_CLIENT_ON_PUBLISH_RECV :
AzureIoTClient 3:9b4e7158ca0d 480 (packet == PUBREL_TYPE) ? MQTT_CLIENT_ON_PUBLISH_REL : MQTT_CLIENT_ON_PUBLISH_COMP;
AzureIoTClient 3:9b4e7158ca0d 481
AzureIoTClient 3:9b4e7158ca0d 482 PUBLISH_ACK publish_ack = { 0 };
AzureIoTClient 3:9b4e7158ca0d 483 publish_ack.packetId = byteutil_read_uint16(&iterator);
Azure.IoT Build 0:ef4901974abc 484
Azure.IoT Build 0:ef4901974abc 485 BUFFER_HANDLE pubRel = NULL;
AzureIoTClient 3:9b4e7158ca0d 486 mqttData->fnOperationCallback(mqttData, action, (void*)&publish_ack, mqttData->ctx);
AzureIoTClient 3:9b4e7158ca0d 487 if (packet == PUBREC_TYPE)
Azure.IoT Build 0:ef4901974abc 488 {
AzureIoTClient 3:9b4e7158ca0d 489 pubRel = mqtt_codec_publishRelease(publish_ack.packetId);
AzureIoTClient 5:34779607059c 490 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 491 {
AzureIoTClient 5:34779607059c 492 LOG(LOG_ERROR, LOG_LINE, "Failed to allocate publish release message.");
AzureIoTClient 5:34779607059c 493 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 494 {
AzureIoTClient 5:34779607059c 495 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 496 }
AzureIoTClient 5:34779607059c 497 }
Azure.IoT Build 0:ef4901974abc 498 }
AzureIoTClient 3:9b4e7158ca0d 499 else if (packet == PUBREL_TYPE)
Azure.IoT Build 0:ef4901974abc 500 {
AzureIoTClient 3:9b4e7158ca0d 501 pubRel = mqtt_codec_publishComplete(publish_ack.packetId);
AzureIoTClient 5:34779607059c 502 if (pubRel == NULL)
AzureIoTClient 5:34779607059c 503 {
AzureIoTClient 5:34779607059c 504 LOG(LOG_ERROR, LOG_LINE, "Failed to allocate publish complete message.");
AzureIoTClient 5:34779607059c 505 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 506 {
AzureIoTClient 5:34779607059c 507 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 508 }
AzureIoTClient 5:34779607059c 509 }
Azure.IoT Build 0:ef4901974abc 510 }
Azure.IoT Build 0:ef4901974abc 511 if (pubRel != NULL)
Azure.IoT Build 0:ef4901974abc 512 {
Azure.IoT Build 0:ef4901974abc 513 (void)sendPacketItem(mqttData, BUFFER_u_char(pubRel), BUFFER_length(pubRel));
Azure.IoT Build 0:ef4901974abc 514 BUFFER_delete(pubRel);
Azure.IoT Build 0:ef4901974abc 515 }
Azure.IoT Build 0:ef4901974abc 516 }
AzureIoTClient 3:9b4e7158ca0d 517 break;
Azure.IoT Build 0:ef4901974abc 518 }
AzureIoTClient 3:9b4e7158ca0d 519 case SUBACK_TYPE:
Azure.IoT Build 0:ef4901974abc 520 {
AzureIoTClient 3:9b4e7158ca0d 521 if (mqttData->fnOperationCallback)
AzureIoTClient 3:9b4e7158ca0d 522 {
AzureIoTClient 3:9b4e7158ca0d 523 /*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 524 SUBSCRIBE_ACK suback = { 0 };
AzureIoTClient 3:9b4e7158ca0d 525
AzureIoTClient 3:9b4e7158ca0d 526 size_t remainLen = len;
AzureIoTClient 3:9b4e7158ca0d 527 suback.packetId = byteutil_read_uint16(&iterator);
AzureIoTClient 3:9b4e7158ca0d 528 remainLen -= 2;
Azure.IoT Build 0:ef4901974abc 529
AzureIoTClient 3:9b4e7158ca0d 530 // Allocate the remaining len
AzureIoTClient 3:9b4e7158ca0d 531 suback.qosReturn = (QOS_VALUE*)malloc(sizeof(QOS_VALUE)*remainLen);
AzureIoTClient 3:9b4e7158ca0d 532 if (suback.qosReturn != NULL)
Azure.IoT Build 0:ef4901974abc 533 {
AzureIoTClient 3:9b4e7158ca0d 534 while (remainLen > 0)
AzureIoTClient 3:9b4e7158ca0d 535 {
AzureIoTClient 3:9b4e7158ca0d 536 suback.qosReturn[suback.qosCount++] = byteutil_readByte(&iterator);
AzureIoTClient 3:9b4e7158ca0d 537 remainLen--;
AzureIoTClient 3:9b4e7158ca0d 538 }
AzureIoTClient 5:34779607059c 539 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_SUBSCRIBE_ACK, (void*)&suback, mqttData->ctx);
AzureIoTClient 3:9b4e7158ca0d 540 free(suback.qosReturn);
Azure.IoT Build 0:ef4901974abc 541 }
AzureIoTClient 5:34779607059c 542 else
AzureIoTClient 5:34779607059c 543 {
AzureIoTClient 5:34779607059c 544 LOG(LOG_ERROR, LOG_LINE, "allocation of quality of service value failed.");
AzureIoTClient 5:34779607059c 545 if (mqttData->fnOperationCallback)
AzureIoTClient 5:34779607059c 546 {
AzureIoTClient 5:34779607059c 547 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_ERROR, NULL, mqttData->ctx);
AzureIoTClient 5:34779607059c 548 }
AzureIoTClient 5:34779607059c 549 }
Azure.IoT Build 0:ef4901974abc 550 }
AzureIoTClient 3:9b4e7158ca0d 551 break;
Azure.IoT Build 0:ef4901974abc 552 }
AzureIoTClient 3:9b4e7158ca0d 553 case UNSUBACK_TYPE:
Azure.IoT Build 0:ef4901974abc 554 {
AzureIoTClient 3:9b4e7158ca0d 555 if (mqttData->fnOperationCallback)
AzureIoTClient 3:9b4e7158ca0d 556 {
AzureIoTClient 3:9b4e7158ca0d 557 /*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 558 UNSUBSCRIBE_ACK unsuback = { 0 };
AzureIoTClient 3:9b4e7158ca0d 559 iterator += VARIABLE_HEADER_OFFSET;
AzureIoTClient 3:9b4e7158ca0d 560 unsuback.packetId = byteutil_read_uint16(&iterator);
Azure.IoT Build 0:ef4901974abc 561
AzureIoTClient 5:34779607059c 562 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_ON_UNSUBSCRIBE_ACK, (void*)&unsuback, mqttData->ctx);
AzureIoTClient 3:9b4e7158ca0d 563 }
AzureIoTClient 3:9b4e7158ca0d 564 break;
Azure.IoT Build 0:ef4901974abc 565 }
AzureIoTClient 3:9b4e7158ca0d 566 case PINGRESP_TYPE:
AzureIoTClient 3:9b4e7158ca0d 567 mqttData->timeSincePing = 0;
AzureIoTClient 3:9b4e7158ca0d 568 // Ping responses do not get forwarded
AzureIoTClient 3:9b4e7158ca0d 569 break;
AzureIoTClient 3:9b4e7158ca0d 570 default:
AzureIoTClient 3:9b4e7158ca0d 571 break;
Azure.IoT Build 0:ef4901974abc 572 }
Azure.IoT Build 0:ef4901974abc 573 }
Azure.IoT Build 0:ef4901974abc 574 }
Azure.IoT Build 0:ef4901974abc 575 }
Azure.IoT Build 0:ef4901974abc 576
Azure.IoT Build 4:e7167dabd6e4 577 MQTT_CLIENT_HANDLE mqtt_client_init(ON_MQTT_MESSAGE_RECV_CALLBACK msgRecv, ON_MQTT_OPERATION_CALLBACK opCallback, void* callbackCtx)
Azure.IoT Build 0:ef4901974abc 578 {
Azure.IoT Build 0:ef4901974abc 579 MQTT_CLIENT* result;
Azure.IoT Build 0:ef4901974abc 580 /*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 581 if (msgRecv == NULL)
Azure.IoT Build 0:ef4901974abc 582 {
Azure.IoT Build 0:ef4901974abc 583 result = NULL;
Azure.IoT Build 0:ef4901974abc 584 }
Azure.IoT Build 0:ef4901974abc 585 else
Azure.IoT Build 0:ef4901974abc 586 {
Azure.IoT Build 0:ef4901974abc 587 result = malloc(sizeof(MQTT_CLIENT));
Azure.IoT Build 0:ef4901974abc 588 if (result == NULL)
Azure.IoT Build 0:ef4901974abc 589 {
Azure.IoT Build 0:ef4901974abc 590 /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
Azure.IoT Build 4:e7167dabd6e4 591 LOG(LOG_ERROR, LOG_LINE, "mqtt_client_init failure: Allocation Failure");
Azure.IoT Build 0:ef4901974abc 592 }
Azure.IoT Build 0:ef4901974abc 593 else
Azure.IoT Build 0:ef4901974abc 594 {
Azure.IoT Build 0:ef4901974abc 595 /*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 596 result->xioHandle = NULL;
Azure.IoT Build 0:ef4901974abc 597 result->packetState = UNKNOWN_TYPE;
Azure.IoT Build 0:ef4901974abc 598 result->packetSendTimeMs = 0;
Azure.IoT Build 0:ef4901974abc 599 result->fnOperationCallback = opCallback;
Azure.IoT Build 0:ef4901974abc 600 result->fnMessageRecv = msgRecv;
Azure.IoT Build 0:ef4901974abc 601 result->ctx = callbackCtx;
Azure.IoT Build 0:ef4901974abc 602 result->qosValue = DELIVER_AT_MOST_ONCE;
Azure.IoT Build 0:ef4901974abc 603 result->keepAliveInterval = 0;
Azure.IoT Build 0:ef4901974abc 604 result->packetTickCntr = tickcounter_create();
Azure.IoT Build 0:ef4901974abc 605 result->mqttOptions.clientId = NULL;
Azure.IoT Build 0:ef4901974abc 606 result->mqttOptions.willTopic = NULL;
Azure.IoT Build 0:ef4901974abc 607 result->mqttOptions.willMessage = NULL;
Azure.IoT Build 0:ef4901974abc 608 result->mqttOptions.username = NULL;
Azure.IoT Build 0:ef4901974abc 609 result->mqttOptions.password = NULL;
Azure.IoT Build 0:ef4901974abc 610 result->socketConnected = false;
Azure.IoT Build 0:ef4901974abc 611 result->clientConnected = false;
Azure.IoT Build 0:ef4901974abc 612 result->logTrace = false;
Azure.IoT Build 0:ef4901974abc 613 result->rawBytesTrace = false;
AzureIoTClient 3:9b4e7158ca0d 614 result->timeSincePing = 0;
AzureIoTClient 3:9b4e7158ca0d 615 result->maxPingRespTime = DEFAULT_MAX_PING_RESPONSE_TIME;
Azure.IoT Build 0:ef4901974abc 616 if (result->packetTickCntr == NULL)
Azure.IoT Build 0:ef4901974abc 617 {
Azure.IoT Build 0:ef4901974abc 618 /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
Azure.IoT Build 4:e7167dabd6e4 619 LOG(LOG_ERROR, LOG_LINE, "mqtt_client_init failure: tickcounter_create failure");
Azure.IoT Build 0:ef4901974abc 620 free(result);
Azure.IoT Build 0:ef4901974abc 621 result = NULL;
Azure.IoT Build 0:ef4901974abc 622 }
Azure.IoT Build 0:ef4901974abc 623 else
Azure.IoT Build 0:ef4901974abc 624 {
Azure.IoT Build 0:ef4901974abc 625 result->codec_handle = mqtt_codec_create(recvCompleteCallback, result);
Azure.IoT Build 0:ef4901974abc 626 if (result->codec_handle == NULL)
Azure.IoT Build 0:ef4901974abc 627 {
Azure.IoT Build 0:ef4901974abc 628 /*Codes_SRS_MQTT_CLIENT_07_002: [If any failure is encountered then mqttclient_init shall return NULL.]*/
Azure.IoT Build 4:e7167dabd6e4 629 LOG(LOG_ERROR, LOG_LINE, "mqtt_client_init failure: mqtt_codec_create failure");
Azure.IoT Build 0:ef4901974abc 630 tickcounter_destroy(result->packetTickCntr);
Azure.IoT Build 0:ef4901974abc 631 free(result);
Azure.IoT Build 0:ef4901974abc 632 result = NULL;
Azure.IoT Build 0:ef4901974abc 633 }
Azure.IoT Build 0:ef4901974abc 634 }
Azure.IoT Build 0:ef4901974abc 635 }
Azure.IoT Build 0:ef4901974abc 636 }
Azure.IoT Build 0:ef4901974abc 637 return result;
Azure.IoT Build 0:ef4901974abc 638 }
Azure.IoT Build 0:ef4901974abc 639
Azure.IoT Build 0:ef4901974abc 640 void mqtt_client_deinit(MQTT_CLIENT_HANDLE handle)
Azure.IoT Build 0:ef4901974abc 641 {
Azure.IoT Build 0:ef4901974abc 642 /*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 643 if (handle != NULL)
Azure.IoT Build 0:ef4901974abc 644 {
Azure.IoT Build 0:ef4901974abc 645 /*Codes_SRS_MQTT_CLIENT_07_005: [mqtt_client_deinit shall deallocate all memory allocated in this unit.]*/
Azure.IoT Build 0:ef4901974abc 646 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 647 tickcounter_destroy(mqttData->packetTickCntr);
Azure.IoT Build 0:ef4901974abc 648 mqtt_codec_destroy(mqttData->codec_handle);
Azure.IoT Build 0:ef4901974abc 649 free(mqttData->mqttOptions.clientId);
Azure.IoT Build 0:ef4901974abc 650 free(mqttData->mqttOptions.willTopic);
Azure.IoT Build 0:ef4901974abc 651 free(mqttData->mqttOptions.willMessage);
Azure.IoT Build 0:ef4901974abc 652 free(mqttData->mqttOptions.username);
Azure.IoT Build 0:ef4901974abc 653 free(mqttData->mqttOptions.password);
Azure.IoT Build 0:ef4901974abc 654 free(mqttData);
Azure.IoT Build 0:ef4901974abc 655 }
Azure.IoT Build 0:ef4901974abc 656 }
Azure.IoT Build 0:ef4901974abc 657
Azure.IoT Build 0:ef4901974abc 658 int mqtt_client_connect(MQTT_CLIENT_HANDLE handle, XIO_HANDLE xioHandle, MQTT_CLIENT_OPTIONS* mqttOptions)
Azure.IoT Build 0:ef4901974abc 659 {
Azure.IoT Build 0:ef4901974abc 660 int result;
Azure.IoT Build 0:ef4901974abc 661 /*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 662 if (handle == NULL || mqttOptions == NULL)
Azure.IoT Build 0:ef4901974abc 663 {
AzureIoTClient 5:34779607059c 664 LOG(LOG_ERROR, LOG_LINE, "mqtt_client_connect: NULL argument (handle = %p, mqttOptions = %p)", handle, mqttOptions);
Azure.IoT Build 0:ef4901974abc 665 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 666 }
Azure.IoT Build 0:ef4901974abc 667 else
Azure.IoT Build 0:ef4901974abc 668 {
Azure.IoT Build 0:ef4901974abc 669 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 670 if (xioHandle == NULL)
Azure.IoT Build 0:ef4901974abc 671 {
Azure.IoT Build 0:ef4901974abc 672 /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 673 LOG(LOG_ERROR, LOG_LINE, "Error: mqttcodec_connect failed");
Azure.IoT Build 0:ef4901974abc 674 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 675 }
Azure.IoT Build 0:ef4901974abc 676 else
Azure.IoT Build 0:ef4901974abc 677 {
Azure.IoT Build 0:ef4901974abc 678 mqttData->xioHandle = xioHandle;
Azure.IoT Build 0:ef4901974abc 679 mqttData->packetState = UNKNOWN_TYPE;
Azure.IoT Build 0:ef4901974abc 680 mqttData->qosValue = mqttOptions->qualityOfServiceValue;
Azure.IoT Build 0:ef4901974abc 681 mqttData->keepAliveInterval = mqttOptions->keepAliveInterval;
AzureIoTClient 3:9b4e7158ca0d 682 mqttData->maxPingRespTime = (DEFAULT_MAX_PING_RESPONSE_TIME < mqttOptions->keepAliveInterval/2) ? DEFAULT_MAX_PING_RESPONSE_TIME : mqttOptions->keepAliveInterval/2;
Azure.IoT Build 0:ef4901974abc 683 if (cloneMqttOptions(mqttData, mqttOptions) != 0)
Azure.IoT Build 0:ef4901974abc 684 {
Azure.IoT Build 4:e7167dabd6e4 685 LOG(LOG_ERROR, LOG_LINE, "Error: Clone Mqtt Options failed");
Azure.IoT Build 0:ef4901974abc 686 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 687 }
Azure.IoT Build 0:ef4901974abc 688 /*Codes_SRS_MQTT_CLIENT_07_008: [mqtt_client_connect shall open the XIO_HANDLE by calling into the xio_open interface.]*/
Azure.IoT Build 0:ef4901974abc 689 else if (xio_open(xioHandle, onOpenComplete, mqttData, onBytesReceived, mqttData, onIoError, mqttData) != 0)
Azure.IoT Build 0:ef4901974abc 690 {
Azure.IoT Build 0:ef4901974abc 691 /*Codes_SRS_MQTT_CLIENT_07_007: [If any failure is encountered then mqtt_client_connect shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 692 LOG(LOG_ERROR, LOG_LINE, "Error: io_open failed");
Azure.IoT Build 0:ef4901974abc 693 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 694 }
Azure.IoT Build 0:ef4901974abc 695 else
Azure.IoT Build 0:ef4901974abc 696 {
Azure.IoT Build 0:ef4901974abc 697 result = 0;
Azure.IoT Build 0:ef4901974abc 698 }
Azure.IoT Build 0:ef4901974abc 699 }
Azure.IoT Build 0:ef4901974abc 700 }
Azure.IoT Build 0:ef4901974abc 701 return result;
Azure.IoT Build 0:ef4901974abc 702 }
Azure.IoT Build 0:ef4901974abc 703
Azure.IoT Build 0:ef4901974abc 704 int mqtt_client_publish(MQTT_CLIENT_HANDLE handle, MQTT_MESSAGE_HANDLE msgHandle)
Azure.IoT Build 0:ef4901974abc 705 {
Azure.IoT Build 0:ef4901974abc 706 int result;
Azure.IoT Build 0:ef4901974abc 707 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 708 if (mqttData == NULL || msgHandle == NULL)
Azure.IoT Build 0:ef4901974abc 709 {
Azure.IoT Build 0:ef4901974abc 710 /*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.]*/
Azure.IoT Build 0:ef4901974abc 711 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 712 }
Azure.IoT Build 0:ef4901974abc 713 else
Azure.IoT Build 0:ef4901974abc 714 {
Azure.IoT Build 0:ef4901974abc 715 /*Codes_SRS_MQTT_CLIENT_07_021: [mqtt_client_publish shall get the message information from the MQTT_MESSAGE_HANDLE.]*/
Azure.IoT Build 0:ef4901974abc 716 const APP_PAYLOAD* payload = mqttmessage_getApplicationMsg(msgHandle);
Azure.IoT Build 0:ef4901974abc 717 if (payload == NULL)
Azure.IoT Build 0:ef4901974abc 718 {
Azure.IoT Build 0:ef4901974abc 719 /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 720 LOG(LOG_ERROR, LOG_LINE, "Error: mqttmessage_getApplicationMsg failed");
Azure.IoT Build 0:ef4901974abc 721 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 722 }
Azure.IoT Build 0:ef4901974abc 723 else
Azure.IoT Build 0:ef4901974abc 724 {
Azure.IoT Build 0:ef4901974abc 725 BUFFER_HANDLE publishPacket = mqtt_codec_publish(mqttmessage_getQosType(msgHandle), mqttmessage_getIsDuplicateMsg(msgHandle),
Azure.IoT Build 0:ef4901974abc 726 mqttmessage_getIsRetained(msgHandle), mqttmessage_getPacketId(msgHandle), mqttmessage_getTopicName(msgHandle), payload->message, payload->length);
Azure.IoT Build 0:ef4901974abc 727 if (publishPacket == NULL)
Azure.IoT Build 0:ef4901974abc 728 {
Azure.IoT Build 0:ef4901974abc 729 /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 730 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_codec_publish failed");
Azure.IoT Build 0:ef4901974abc 731 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 732 }
Azure.IoT Build 0:ef4901974abc 733 else
Azure.IoT Build 0:ef4901974abc 734 {
Azure.IoT Build 0:ef4901974abc 735 mqttData->packetState = PUBLISH_TYPE;
Azure.IoT Build 0:ef4901974abc 736
Azure.IoT Build 0:ef4901974abc 737 /*Codes_SRS_MQTT_CLIENT_07_022: [On success mqtt_client_publish shall send the MQTT SUBCRIBE packet to the endpoint.]*/
Azure.IoT Build 0:ef4901974abc 738 if (sendPacketItem(mqttData, BUFFER_u_char(publishPacket), BUFFER_length(publishPacket)) != 0)
Azure.IoT Build 0:ef4901974abc 739 {
Azure.IoT Build 0:ef4901974abc 740 /*Codes_SRS_MQTT_CLIENT_07_020: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 741 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_client_publish send failed");
Azure.IoT Build 0:ef4901974abc 742 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 743 }
Azure.IoT Build 0:ef4901974abc 744 else
Azure.IoT Build 0:ef4901974abc 745 {
Azure.IoT Build 0:ef4901974abc 746 result = 0;
Azure.IoT Build 0:ef4901974abc 747 }
Azure.IoT Build 0:ef4901974abc 748 BUFFER_delete(publishPacket);
Azure.IoT Build 0:ef4901974abc 749 }
Azure.IoT Build 0:ef4901974abc 750 }
Azure.IoT Build 0:ef4901974abc 751 }
Azure.IoT Build 0:ef4901974abc 752 return result;
Azure.IoT Build 0:ef4901974abc 753 }
Azure.IoT Build 0:ef4901974abc 754
Azure.IoT Build 0:ef4901974abc 755 int mqtt_client_subscribe(MQTT_CLIENT_HANDLE handle, uint16_t packetId, SUBSCRIBE_PAYLOAD* subscribeList, size_t count)
Azure.IoT Build 0:ef4901974abc 756 {
Azure.IoT Build 0:ef4901974abc 757 int result;
Azure.IoT Build 0:ef4901974abc 758 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 759 if (mqttData == NULL || subscribeList == NULL || count == 0)
Azure.IoT Build 0:ef4901974abc 760 {
Azure.IoT Build 0:ef4901974abc 761 /*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.]*/
Azure.IoT Build 0:ef4901974abc 762 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 763 }
Azure.IoT Build 0:ef4901974abc 764 else
Azure.IoT Build 0:ef4901974abc 765 {
Azure.IoT Build 0:ef4901974abc 766 BUFFER_HANDLE subPacket = mqtt_codec_subscribe(packetId, subscribeList, count);
Azure.IoT Build 0:ef4901974abc 767 if (subPacket == NULL)
Azure.IoT Build 0:ef4901974abc 768 {
Azure.IoT Build 0:ef4901974abc 769 /*Codes_SRS_MQTT_CLIENT_07_014: [If any failure is encountered then mqtt_client_subscribe shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 770 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_codec_subscribe failed");
Azure.IoT Build 0:ef4901974abc 771 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 772 }
Azure.IoT Build 0:ef4901974abc 773 else
Azure.IoT Build 0:ef4901974abc 774 {
Azure.IoT Build 0:ef4901974abc 775 mqttData->packetState = SUBSCRIBE_TYPE;
Azure.IoT Build 0:ef4901974abc 776
Azure.IoT Build 0:ef4901974abc 777 /*Codes_SRS_MQTT_CLIENT_07_015: [On success mqtt_client_subscribe shall send the MQTT SUBCRIBE packet to the endpoint.]*/
Azure.IoT Build 0:ef4901974abc 778 if (sendPacketItem(mqttData, BUFFER_u_char(subPacket), BUFFER_length(subPacket)) != 0)
Azure.IoT Build 0:ef4901974abc 779 {
Azure.IoT Build 0:ef4901974abc 780 /*Codes_SRS_MQTT_CLIENT_07_014: [If any failure is encountered then mqtt_client_subscribe shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 781 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_client_subscribe send failed");
Azure.IoT Build 0:ef4901974abc 782 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 783 }
Azure.IoT Build 0:ef4901974abc 784 else
Azure.IoT Build 0:ef4901974abc 785 {
Azure.IoT Build 0:ef4901974abc 786 result = 0;
Azure.IoT Build 0:ef4901974abc 787 }
Azure.IoT Build 0:ef4901974abc 788 BUFFER_delete(subPacket);
Azure.IoT Build 0:ef4901974abc 789 }
Azure.IoT Build 0:ef4901974abc 790 }
Azure.IoT Build 0:ef4901974abc 791 return result;
Azure.IoT Build 0:ef4901974abc 792 }
Azure.IoT Build 0:ef4901974abc 793
Azure.IoT Build 0:ef4901974abc 794 int mqtt_client_unsubscribe(MQTT_CLIENT_HANDLE handle, uint16_t packetId, const char** unsubscribeList, size_t count)
Azure.IoT Build 0:ef4901974abc 795 {
Azure.IoT Build 0:ef4901974abc 796 int result;
Azure.IoT Build 0:ef4901974abc 797 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 798 if (mqttData == NULL || unsubscribeList == NULL || count == 0)
Azure.IoT Build 0:ef4901974abc 799 {
Azure.IoT Build 0:ef4901974abc 800 /*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.]*/
Azure.IoT Build 0:ef4901974abc 801 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 802 }
Azure.IoT Build 0:ef4901974abc 803 else
Azure.IoT Build 0:ef4901974abc 804 {
Azure.IoT Build 0:ef4901974abc 805 BUFFER_HANDLE unsubPacket = mqtt_codec_unsubscribe(packetId, unsubscribeList, count);
Azure.IoT Build 0:ef4901974abc 806 if (unsubPacket == NULL)
Azure.IoT Build 0:ef4901974abc 807 {
Azure.IoT Build 0:ef4901974abc 808 /*Codes_SRS_MQTT_CLIENT_07_017: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 809 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_codec_unsubscribe failed");
Azure.IoT Build 0:ef4901974abc 810 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 811 }
Azure.IoT Build 0:ef4901974abc 812 else
Azure.IoT Build 0:ef4901974abc 813 {
Azure.IoT Build 0:ef4901974abc 814 mqttData->packetState = UNSUBSCRIBE_TYPE;
Azure.IoT Build 0:ef4901974abc 815
Azure.IoT Build 0:ef4901974abc 816 /*Codes_SRS_MQTT_CLIENT_07_018: [On success mqtt_client_unsubscribe shall send the MQTT SUBCRIBE packet to the endpoint.]*/
Azure.IoT Build 0:ef4901974abc 817 if (sendPacketItem(mqttData, BUFFER_u_char(unsubPacket), BUFFER_length(unsubPacket)) != 0)
Azure.IoT Build 0:ef4901974abc 818 {
Azure.IoT Build 0:ef4901974abc 819 /*Codes_SRS_MQTT_CLIENT_07_017: [If any failure is encountered then mqtt_client_unsubscribe shall return a non-zero value.].]*/
Azure.IoT Build 4:e7167dabd6e4 820 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_client_unsubscribe send failed");
Azure.IoT Build 0:ef4901974abc 821 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 822 }
Azure.IoT Build 0:ef4901974abc 823 else
Azure.IoT Build 0:ef4901974abc 824 {
Azure.IoT Build 0:ef4901974abc 825 result = 0;
Azure.IoT Build 0:ef4901974abc 826 }
Azure.IoT Build 0:ef4901974abc 827 BUFFER_delete(unsubPacket);
Azure.IoT Build 0:ef4901974abc 828 }
Azure.IoT Build 0:ef4901974abc 829 }
Azure.IoT Build 0:ef4901974abc 830 return result;
Azure.IoT Build 0:ef4901974abc 831 }
Azure.IoT Build 0:ef4901974abc 832
Azure.IoT Build 0:ef4901974abc 833 int mqtt_client_disconnect(MQTT_CLIENT_HANDLE handle)
Azure.IoT Build 0:ef4901974abc 834 {
Azure.IoT Build 0:ef4901974abc 835 int result;
Azure.IoT Build 0:ef4901974abc 836 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 837 if (mqttData == NULL)
Azure.IoT Build 0:ef4901974abc 838 {
Azure.IoT Build 0:ef4901974abc 839 /*Codes_SRS_MQTT_CLIENT_07_010: [If the parameters handle is NULL then mqtt_client_disconnect shall return a non-zero value.]*/
Azure.IoT Build 0:ef4901974abc 840 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 841 }
Azure.IoT Build 0:ef4901974abc 842 else
Azure.IoT Build 0:ef4901974abc 843 {
Azure.IoT Build 0:ef4901974abc 844 BUFFER_HANDLE disconnectPacket = mqtt_codec_disconnect();
Azure.IoT Build 0:ef4901974abc 845 if (disconnectPacket == NULL)
Azure.IoT Build 0:ef4901974abc 846 {
Azure.IoT Build 0:ef4901974abc 847 /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 848 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect failed");
Azure.IoT Build 4:e7167dabd6e4 849 mqttData->packetState = PACKET_TYPE_ERROR;
Azure.IoT Build 0:ef4901974abc 850 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 851 }
Azure.IoT Build 0:ef4901974abc 852 else
Azure.IoT Build 0:ef4901974abc 853 {
Azure.IoT Build 0:ef4901974abc 854 mqttData->packetState = DISCONNECT_TYPE;
Azure.IoT Build 0:ef4901974abc 855
Azure.IoT Build 0:ef4901974abc 856 /*Codes_SRS_MQTT_CLIENT_07_012: [On success mqtt_client_disconnect shall send the MQTT DISCONNECT packet to the endpoint.]*/
Azure.IoT Build 0:ef4901974abc 857 if (sendPacketItem(mqttData, BUFFER_u_char(disconnectPacket), BUFFER_length(disconnectPacket)) != 0)
Azure.IoT Build 0:ef4901974abc 858 {
Azure.IoT Build 0:ef4901974abc 859 /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
Azure.IoT Build 4:e7167dabd6e4 860 LOG(LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect send failed");
Azure.IoT Build 0:ef4901974abc 861 result = __LINE__;
Azure.IoT Build 0:ef4901974abc 862 }
Azure.IoT Build 0:ef4901974abc 863 else
Azure.IoT Build 0:ef4901974abc 864 {
Azure.IoT Build 0:ef4901974abc 865 result = 0;
Azure.IoT Build 0:ef4901974abc 866 }
Azure.IoT Build 0:ef4901974abc 867 BUFFER_delete(disconnectPacket);
Azure.IoT Build 0:ef4901974abc 868 }
Azure.IoT Build 0:ef4901974abc 869 }
Azure.IoT Build 0:ef4901974abc 870 return result;
Azure.IoT Build 0:ef4901974abc 871 }
Azure.IoT Build 0:ef4901974abc 872
Azure.IoT Build 0:ef4901974abc 873 void mqtt_client_dowork(MQTT_CLIENT_HANDLE handle)
Azure.IoT Build 0:ef4901974abc 874 {
Azure.IoT Build 0:ef4901974abc 875 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 876 /*Codes_SRS_MQTT_CLIENT_07_023: [If the parameter handle is NULL then mqtt_client_dowork shall do nothing.]*/
Azure.IoT Build 0:ef4901974abc 877 if (mqttData != NULL)
Azure.IoT Build 0:ef4901974abc 878 {
Azure.IoT Build 0:ef4901974abc 879 /*Codes_SRS_MQTT_CLIENT_07_024: [mqtt_client_dowork shall call the xio_dowork function to complete operations.]*/
Azure.IoT Build 0:ef4901974abc 880 xio_dowork(mqttData->xioHandle);
Azure.IoT Build 0:ef4901974abc 881
Azure.IoT Build 0:ef4901974abc 882 /*Codes_SRS_MQTT_CLIENT_07_025: [mqtt_client_dowork shall retrieve the the last packet send value and ...]*/
Azure.IoT Build 0:ef4901974abc 883 if (mqttData->socketConnected && mqttData->clientConnected && mqttData->keepAliveInterval > 0)
Azure.IoT Build 0:ef4901974abc 884 {
Azure.IoT Build 0:ef4901974abc 885 uint64_t current_ms;
Azure.IoT Build 0:ef4901974abc 886 if (tickcounter_get_current_ms(mqttData->packetTickCntr, &current_ms) != 0)
Azure.IoT Build 0:ef4901974abc 887 {
Azure.IoT Build 4:e7167dabd6e4 888 LOG(LOG_ERROR, LOG_LINE, "Error: tickcounter_get_current_ms failed");
Azure.IoT Build 0:ef4901974abc 889 }
Azure.IoT Build 0:ef4901974abc 890 else
Azure.IoT Build 0:ef4901974abc 891 {
AzureIoTClient 3:9b4e7158ca0d 892 /* Codes_SRS_MQTT_CLIENT_07_035: [If the timeSincePing has expired past the maxPingRespTime then mqtt_client_dowork shall call the Operation Callback function with the message MQTT_CLIENT_NO_PING_RESPONSE] */
AzureIoTClient 3:9b4e7158ca0d 893 if (mqttData->timeSincePing > 0 && ((current_ms - mqttData->timeSincePing)/1000) > mqttData->maxPingRespTime)
AzureIoTClient 3:9b4e7158ca0d 894 {
AzureIoTClient 3:9b4e7158ca0d 895 // We haven't gotten a ping response in the alloted time
AzureIoTClient 3:9b4e7158ca0d 896 if (mqttData->fnOperationCallback != NULL)
AzureIoTClient 3:9b4e7158ca0d 897 {
AzureIoTClient 3:9b4e7158ca0d 898 mqttData->fnOperationCallback(mqttData, MQTT_CLIENT_NO_PING_RESPONSE, NULL, mqttData->ctx);
AzureIoTClient 3:9b4e7158ca0d 899 }
AzureIoTClient 3:9b4e7158ca0d 900 mqttData->socketConnected = false;
AzureIoTClient 3:9b4e7158ca0d 901 mqttData->clientConnected = false;
AzureIoTClient 3:9b4e7158ca0d 902 mqttData->timeSincePing = 0;
AzureIoTClient 3:9b4e7158ca0d 903 mqttData->packetSendTimeMs = 0;
AzureIoTClient 3:9b4e7158ca0d 904 mqttData->packetState = UNKNOWN_TYPE;
AzureIoTClient 3:9b4e7158ca0d 905 }
AzureIoTClient 3:9b4e7158ca0d 906 else if ((((current_ms - mqttData->packetSendTimeMs) / 1000) + KEEP_ALIVE_BUFFER_SEC) > mqttData->keepAliveInterval)
Azure.IoT Build 0:ef4901974abc 907 {
Azure.IoT Build 0:ef4901974abc 908 /*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 909 BUFFER_HANDLE pingPacket = mqtt_codec_ping();
Azure.IoT Build 0:ef4901974abc 910 if (pingPacket != NULL)
Azure.IoT Build 0:ef4901974abc 911 {
Azure.IoT Build 0:ef4901974abc 912 (void)sendPacketItem(mqttData, BUFFER_u_char(pingPacket), BUFFER_length(pingPacket));
Azure.IoT Build 0:ef4901974abc 913 BUFFER_delete(pingPacket);
AzureIoTClient 3:9b4e7158ca0d 914 (void)tickcounter_get_current_ms(mqttData->packetTickCntr, &mqttData->timeSincePing);
Azure.IoT Build 0:ef4901974abc 915 }
Azure.IoT Build 0:ef4901974abc 916 }
Azure.IoT Build 0:ef4901974abc 917 }
Azure.IoT Build 0:ef4901974abc 918 }
Azure.IoT Build 0:ef4901974abc 919 }
Azure.IoT Build 0:ef4901974abc 920 }
Azure.IoT Build 0:ef4901974abc 921
Azure.IoT Build 0:ef4901974abc 922 void mqtt_client_set_trace(MQTT_CLIENT_HANDLE handle, bool traceOn, bool rawBytesOn)
Azure.IoT Build 0:ef4901974abc 923 {
Azure.IoT Build 0:ef4901974abc 924 MQTT_CLIENT* mqttData = (MQTT_CLIENT*)handle;
Azure.IoT Build 0:ef4901974abc 925 if (mqttData != NULL)
Azure.IoT Build 0:ef4901974abc 926 {
Azure.IoT Build 0:ef4901974abc 927 mqttData->logTrace = traceOn;
Azure.IoT Build 0:ef4901974abc 928 mqttData->rawBytesTrace = rawBytesOn;
Azure.IoT Build 0:ef4901974abc 929 }
Azure.IoT Build 0:ef4901974abc 930 }