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