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