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:
Mon Sep 11 09:23:23 2017 -0700
Revision:
19:e283dcf26037
Parent:
18:6d13ad04e8a0
Child:
23:80794cfb3565
1.1.23

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