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:
Wed Jan 17 08:57:29 2018 -0800
Revision:
23:80794cfb3565
Parent:
19:e283dcf26037
Child:
24:75f5b91d1c6e
1.1.30

Who changed what in which revision?

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