Changes to enabled on-line compiler

Committer:
JMF
Date:
Wed May 30 20:59:51 2018 +0000
Revision:
0:082731ede69f
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
JMF 0:082731ede69f 1 /*
JMF 0:082731ede69f 2 * Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved.
JMF 0:082731ede69f 3 *
JMF 0:082731ede69f 4 * Licensed under the Apache License, Version 2.0 (the "License").
JMF 0:082731ede69f 5 * You may not use this file except in compliance with the License.
JMF 0:082731ede69f 6 * A copy of the License is located at
JMF 0:082731ede69f 7 *
JMF 0:082731ede69f 8 * http://aws.amazon.com/apache2.0
JMF 0:082731ede69f 9 *
JMF 0:082731ede69f 10 * or in the "license" file accompanying this file. This file is distributed
JMF 0:082731ede69f 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
JMF 0:082731ede69f 12 * express or implied. See the License for the specific language governing
JMF 0:082731ede69f 13 * permissions and limitations under the License.
JMF 0:082731ede69f 14 */
JMF 0:082731ede69f 15
JMF 0:082731ede69f 16 // Based on Eclipse Paho.
JMF 0:082731ede69f 17 /*******************************************************************************
JMF 0:082731ede69f 18 * Copyright (c) 2014 IBM Corp.
JMF 0:082731ede69f 19 *
JMF 0:082731ede69f 20 * All rights reserved. This program and the accompanying materials
JMF 0:082731ede69f 21 * are made available under the terms of the Eclipse Public License v1.0
JMF 0:082731ede69f 22 * and Eclipse Distribution License v1.0 which accompany this distribution.
JMF 0:082731ede69f 23 *
JMF 0:082731ede69f 24 * The Eclipse Public License is available at
JMF 0:082731ede69f 25 * http://www.eclipse.org/legal/epl-v10.html
JMF 0:082731ede69f 26 * and the Eclipse Distribution License is available at
JMF 0:082731ede69f 27 * http://www.eclipse.org/org/documents/edl-v10.php.
JMF 0:082731ede69f 28 *
JMF 0:082731ede69f 29 * Contributors:
JMF 0:082731ede69f 30 * Ian Craggs - initial API and implementation and/or initial documentation
JMF 0:082731ede69f 31 *******************************************************************************/
JMF 0:082731ede69f 32
JMF 0:082731ede69f 33 /**
JMF 0:082731ede69f 34 * @file aws_iot_mqtt_client_subscribe.c
JMF 0:082731ede69f 35 * @brief MQTT client subscribe API definitions
JMF 0:082731ede69f 36 */
JMF 0:082731ede69f 37
JMF 0:082731ede69f 38 #ifdef __cplusplus
JMF 0:082731ede69f 39 extern "C" {
JMF 0:082731ede69f 40 #endif
JMF 0:082731ede69f 41
JMF 0:082731ede69f 42 #include "aws_iot_mqtt_client_common_internal.h"
JMF 0:082731ede69f 43
JMF 0:082731ede69f 44 /**
JMF 0:082731ede69f 45 * Serializes the supplied subscribe data into the supplied buffer, ready for sending
JMF 0:082731ede69f 46 * @param pTxBuf the buffer into which the packet will be serialized
JMF 0:082731ede69f 47 * @param txBufLen the length in bytes of the supplied buffer
JMF 0:082731ede69f 48 * @param dup unsigned char - the MQTT dup flag
JMF 0:082731ede69f 49 * @param packetId uint16_t - the MQTT packet identifier
JMF 0:082731ede69f 50 * @param topicCount - number of members in the topicFilters and reqQos arrays
JMF 0:082731ede69f 51 * @param pTopicNameList - array of topic filter names
JMF 0:082731ede69f 52 * @param pTopicNameLenList - array of length of topic filter names
JMF 0:082731ede69f 53 * @param pRequestedQoSs - array of requested QoS
JMF 0:082731ede69f 54 * @param pSerializedLen - the length of the serialized data
JMF 0:082731ede69f 55 *
JMF 0:082731ede69f 56 * @return An IoT Error Type defining successful/failed operation
JMF 0:082731ede69f 57 */
JMF 0:082731ede69f 58 static IoT_Error_t _aws_iot_mqtt_serialize_subscribe(unsigned char *pTxBuf, size_t txBufLen,
JMF 0:082731ede69f 59 unsigned char dup, uint16_t packetId, uint32_t topicCount,
JMF 0:082731ede69f 60 const char **pTopicNameList, uint16_t *pTopicNameLenList,
JMF 0:082731ede69f 61 QoS *pRequestedQoSs, uint32_t *pSerializedLen) {
JMF 0:082731ede69f 62 unsigned char *ptr;
JMF 0:082731ede69f 63 uint32_t itr, rem_len;
JMF 0:082731ede69f 64 IoT_Error_t rc;
JMF 0:082731ede69f 65 MQTTHeader header = {0};
JMF 0:082731ede69f 66
JMF 0:082731ede69f 67 FUNC_ENTRY;
JMF 0:082731ede69f 68 if(NULL == pTxBuf || NULL == pSerializedLen) {
JMF 0:082731ede69f 69 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 70 }
JMF 0:082731ede69f 71
JMF 0:082731ede69f 72 ptr = pTxBuf;
JMF 0:082731ede69f 73 rem_len = 2; /* packetId */
JMF 0:082731ede69f 74
JMF 0:082731ede69f 75 for(itr = 0; itr < topicCount; ++itr) {
JMF 0:082731ede69f 76 rem_len += (uint32_t) (pTopicNameLenList[itr] + 2 + 1); /* topic + length + req_qos */
JMF 0:082731ede69f 77 }
JMF 0:082731ede69f 78
JMF 0:082731ede69f 79 if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) {
JMF 0:082731ede69f 80 FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR);
JMF 0:082731ede69f 81 }
JMF 0:082731ede69f 82
JMF 0:082731ede69f 83 rc = aws_iot_mqtt_internal_init_header(&header, SUBSCRIBE, QOS1, dup, 0);
JMF 0:082731ede69f 84 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 85 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 86 }
JMF 0:082731ede69f 87 /* write header */
JMF 0:082731ede69f 88 aws_iot_mqtt_internal_write_char(&ptr, header.byte);
JMF 0:082731ede69f 89
JMF 0:082731ede69f 90 /* write remaining length */
JMF 0:082731ede69f 91 ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len);
JMF 0:082731ede69f 92
JMF 0:082731ede69f 93 aws_iot_mqtt_internal_write_uint_16(&ptr, packetId);
JMF 0:082731ede69f 94
JMF 0:082731ede69f 95 for(itr = 0; itr < topicCount; ++itr) {
JMF 0:082731ede69f 96 aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[itr], pTopicNameLenList[itr]);
JMF 0:082731ede69f 97 aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pRequestedQoSs[itr]);
JMF 0:082731ede69f 98 }
JMF 0:082731ede69f 99
JMF 0:082731ede69f 100 *pSerializedLen = (uint32_t) (ptr - pTxBuf);
JMF 0:082731ede69f 101
JMF 0:082731ede69f 102 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 103 }
JMF 0:082731ede69f 104
JMF 0:082731ede69f 105 /**
JMF 0:082731ede69f 106 * Deserializes the supplied (wire) buffer into suback data
JMF 0:082731ede69f 107 * @param pPacketId returned integer - the MQTT packet identifier
JMF 0:082731ede69f 108 * @param maxExpectedQoSCount - the maximum number of members allowed in the grantedQoSs array
JMF 0:082731ede69f 109 * @param pGrantedQoSCount returned uint32_t - number of members in the grantedQoSs array
JMF 0:082731ede69f 110 * @param pGrantedQoSs returned array of QoS type - the granted qualities of service
JMF 0:082731ede69f 111 * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field
JMF 0:082731ede69f 112 * @param rxBufLen the length in bytes of the data in the supplied buffer
JMF 0:082731ede69f 113 *
JMF 0:082731ede69f 114 * @return An IoT Error Type defining successful/failed operation
JMF 0:082731ede69f 115 */
JMF 0:082731ede69f 116 static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_t maxExpectedQoSCount,
JMF 0:082731ede69f 117 uint32_t *pGrantedQoSCount, QoS *pGrantedQoSs,
JMF 0:082731ede69f 118 unsigned char *pRxBuf, size_t rxBufLen) {
JMF 0:082731ede69f 119 unsigned char *curData, *endData;
JMF 0:082731ede69f 120 uint32_t decodedLen, readBytesLen;
JMF 0:082731ede69f 121 IoT_Error_t decodeRc;
JMF 0:082731ede69f 122 MQTTHeader header = {0};
JMF 0:082731ede69f 123
JMF 0:082731ede69f 124 FUNC_ENTRY;
JMF 0:082731ede69f 125 if(NULL == pPacketId || NULL == pGrantedQoSCount || NULL == pGrantedQoSs) {
JMF 0:082731ede69f 126 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 127 }
JMF 0:082731ede69f 128
JMF 0:082731ede69f 129 curData = pRxBuf;
JMF 0:082731ede69f 130 endData = NULL;
JMF 0:082731ede69f 131 decodeRc = FAILURE;
JMF 0:082731ede69f 132 decodedLen = 0;
JMF 0:082731ede69f 133 readBytesLen = 0;
JMF 0:082731ede69f 134
JMF 0:082731ede69f 135 /* SUBACK header size is 4 bytes for header and at least one byte for QoS payload
JMF 0:082731ede69f 136 * Need at least a 5 bytes buffer. MQTT3.1.1 specification 3.9
JMF 0:082731ede69f 137 */
JMF 0:082731ede69f 138 if(5 > rxBufLen) {
JMF 0:082731ede69f 139 FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
JMF 0:082731ede69f 140 }
JMF 0:082731ede69f 141
JMF 0:082731ede69f 142 header.byte = aws_iot_mqtt_internal_read_char(&curData);
JMF 0:082731ede69f 143 if(SUBACK != MQTT_HEADER_FIELD_TYPE(header.byte)) {
JMF 0:082731ede69f 144 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 145 }
JMF 0:082731ede69f 146
JMF 0:082731ede69f 147 /* read remaining length */
JMF 0:082731ede69f 148 decodeRc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen);
JMF 0:082731ede69f 149 if(AWS_SUCCESS != decodeRc) {
JMF 0:082731ede69f 150 FUNC_EXIT_RC(decodeRc);
JMF 0:082731ede69f 151 }
JMF 0:082731ede69f 152
JMF 0:082731ede69f 153 curData += (readBytesLen);
JMF 0:082731ede69f 154 endData = curData + decodedLen;
JMF 0:082731ede69f 155 if(endData - curData < 2) {
JMF 0:082731ede69f 156 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 157 }
JMF 0:082731ede69f 158
JMF 0:082731ede69f 159 *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData);
JMF 0:082731ede69f 160
JMF 0:082731ede69f 161 *pGrantedQoSCount = 0;
JMF 0:082731ede69f 162 while(curData < endData) {
JMF 0:082731ede69f 163 if(*pGrantedQoSCount > maxExpectedQoSCount) {
JMF 0:082731ede69f 164 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 165 }
JMF 0:082731ede69f 166 pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS) aws_iot_mqtt_internal_read_char(&curData);
JMF 0:082731ede69f 167 }
JMF 0:082731ede69f 168
JMF 0:082731ede69f 169 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 170 }
JMF 0:082731ede69f 171
JMF 0:082731ede69f 172 /* Returns MAX_MESSAGE_HANDLERS value if no free index is available */
JMF 0:082731ede69f 173 static uint32_t _aws_iot_mqtt_get_free_message_handler_index(AWS_IoT_Client *pClient) {
JMF 0:082731ede69f 174 uint32_t itr;
JMF 0:082731ede69f 175
JMF 0:082731ede69f 176 FUNC_ENTRY;
JMF 0:082731ede69f 177
JMF 0:082731ede69f 178 for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; itr++) {
JMF 0:082731ede69f 179 if(pClient->clientData.messageHandlers[itr].topicName == NULL) {
JMF 0:082731ede69f 180 break;
JMF 0:082731ede69f 181 }
JMF 0:082731ede69f 182 }
JMF 0:082731ede69f 183
JMF 0:082731ede69f 184 FUNC_EXIT_RC((int)itr);
JMF 0:082731ede69f 185 }
JMF 0:082731ede69f 186
JMF 0:082731ede69f 187 /**
JMF 0:082731ede69f 188 * @brief Subscribe to an MQTT topic.
JMF 0:082731ede69f 189 *
JMF 0:082731ede69f 190 * Called to send a subscribe message to the broker requesting a subscription
JMF 0:082731ede69f 191 * to an MQTT topic. This is the internal function which is called by the
JMF 0:082731ede69f 192 * subscribe API to perform the operation. Not meant to be called directly as
JMF 0:082731ede69f 193 * it doesn't do validations or client state changes
JMF 0:082731ede69f 194 * @note Call is blocking. The call returns after the receipt of the SUBACK control packet.
JMF 0:082731ede69f 195 * @warning pTopicName and pApplicationHandlerData need to be static in memory.
JMF 0:082731ede69f 196 *
JMF 0:082731ede69f 197 * @param pClient Reference to the IoT Client
JMF 0:082731ede69f 198 * @param pTopicName Topic Name to publish to. pTopicName needs to be static in memory since
JMF 0:082731ede69f 199 * no malloc are performed by the SDK
JMF 0:082731ede69f 200 * @param topicNameLen Length of the topic name
JMF 0:082731ede69f 201 * @param pApplicationHandler_t Reference to the handler function for this subscription
JMF 0:082731ede69f 202 * @param pApplicationHandlerData Point to data passed to the callback.
JMF 0:082731ede69f 203 * pApplicationHandlerData also needs to be static in memory since no malloc are performed by the SDK
JMF 0:082731ede69f 204 *
JMF 0:082731ede69f 205 * @return An IoT Error Type defining successful/failed subscription
JMF 0:082731ede69f 206 */
JMF 0:082731ede69f 207 static IoT_Error_t _aws_iot_mqtt_internal_subscribe(AWS_IoT_Client *pClient, const char *pTopicName,
JMF 0:082731ede69f 208 uint16_t topicNameLen, QoS qos,
JMF 0:082731ede69f 209 pApplicationHandler_t pApplicationHandler,
JMF 0:082731ede69f 210 void *pApplicationHandlerData) {
JMF 0:082731ede69f 211 uint16_t txPacketId, rxPacketId;
JMF 0:082731ede69f 212 uint32_t serializedLen, indexOfFreeMessageHandler, count;
JMF 0:082731ede69f 213 IoT_Error_t rc;
JMF 0:082731ede69f 214 awsTimer timer;
JMF 0:082731ede69f 215 QoS grantedQoS[3] = {QOS0, QOS0, QOS0};
JMF 0:082731ede69f 216
JMF 0:082731ede69f 217 FUNC_ENTRY;
JMF 0:082731ede69f 218 init_timer(&timer);
JMF 0:082731ede69f 219 countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
JMF 0:082731ede69f 220
JMF 0:082731ede69f 221 serializedLen = 0;
JMF 0:082731ede69f 222 count = 0;
JMF 0:082731ede69f 223 txPacketId = aws_iot_mqtt_get_next_packet_id(pClient);
JMF 0:082731ede69f 224 rxPacketId = 0;
JMF 0:082731ede69f 225
JMF 0:082731ede69f 226 rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0,
JMF 0:082731ede69f 227 txPacketId, 1, &pTopicName, &topicNameLen, &qos, &serializedLen);
JMF 0:082731ede69f 228 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 229 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 230 }
JMF 0:082731ede69f 231
JMF 0:082731ede69f 232 indexOfFreeMessageHandler = _aws_iot_mqtt_get_free_message_handler_index(pClient);
JMF 0:082731ede69f 233 if(AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS <= indexOfFreeMessageHandler) {
JMF 0:082731ede69f 234 FUNC_EXIT_RC(MQTT_MAX_SUBSCRIPTIONS_REACHED_ERROR);
JMF 0:082731ede69f 235 }
JMF 0:082731ede69f 236
JMF 0:082731ede69f 237 /* send the subscribe packet */
JMF 0:082731ede69f 238 rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer);
JMF 0:082731ede69f 239 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 240 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 241 }
JMF 0:082731ede69f 242
JMF 0:082731ede69f 243 /* wait for suback */
JMF 0:082731ede69f 244 rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer);
JMF 0:082731ede69f 245 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 246 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 247 }
JMF 0:082731ede69f 248
JMF 0:082731ede69f 249 /* Granted QoS can be 0, 1 or 2 */
JMF 0:082731ede69f 250 rc = _aws_iot_mqtt_deserialize_suback(&rxPacketId, 1, &count, grantedQoS, pClient->clientData.readBuf,
JMF 0:082731ede69f 251 pClient->clientData.readBufSize);
JMF 0:082731ede69f 252 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 253 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 254 }
JMF 0:082731ede69f 255
JMF 0:082731ede69f 256 /* TODO : Figure out how to test this before activating this check */
JMF 0:082731ede69f 257 //if(txPacketId != rxPacketId) {
JMF 0:082731ede69f 258 /* Different SUBACK received than expected. Return error
JMF 0:082731ede69f 259 * This can cause issues if the request timeout value is too small */
JMF 0:082731ede69f 260 // return RX_MESSAGE_INVALID_ERROR;
JMF 0:082731ede69f 261 //}
JMF 0:082731ede69f 262
JMF 0:082731ede69f 263 pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicName =
JMF 0:082731ede69f 264 pTopicName;
JMF 0:082731ede69f 265 pClient->clientData.messageHandlers[indexOfFreeMessageHandler].topicNameLen =
JMF 0:082731ede69f 266 topicNameLen;
JMF 0:082731ede69f 267 pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandler =
JMF 0:082731ede69f 268 pApplicationHandler;
JMF 0:082731ede69f 269 pClient->clientData.messageHandlers[indexOfFreeMessageHandler].pApplicationHandlerData =
JMF 0:082731ede69f 270 pApplicationHandlerData;
JMF 0:082731ede69f 271 pClient->clientData.messageHandlers[indexOfFreeMessageHandler].qos = qos;
JMF 0:082731ede69f 272
JMF 0:082731ede69f 273 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 274 }
JMF 0:082731ede69f 275
JMF 0:082731ede69f 276 /**
JMF 0:082731ede69f 277 * @brief Subscribe to an MQTT topic.
JMF 0:082731ede69f 278 *
JMF 0:082731ede69f 279 * Called to send a subscribe message to the broker requesting a subscription
JMF 0:082731ede69f 280 * to an MQTT topic. This is the outer function which does the validations and
JMF 0:082731ede69f 281 * calls the internal subscribe above to perform the actual operation.
JMF 0:082731ede69f 282 * It is also responsible for client state changes
JMF 0:082731ede69f 283 * @note Call is blocking. The call returns after the receipt of the SUBACK control packet.
JMF 0:082731ede69f 284 * @warning pTopicName and pApplicationHandlerData need to be static in memory.
JMF 0:082731ede69f 285 *
JMF 0:082731ede69f 286 * @param pClient Reference to the IoT Client
JMF 0:082731ede69f 287 * @param pTopicName Topic Name to publish to. pTopicName needs to be static in memory since
JMF 0:082731ede69f 288 * no malloc are performed by the SDK
JMF 0:082731ede69f 289 * @param topicNameLen Length of the topic name
JMF 0:082731ede69f 290 * @param pApplicationHandler_t Reference to the handler function for this subscription
JMF 0:082731ede69f 291 * @param pApplicationHandlerData Point to data passed to the callback.
JMF 0:082731ede69f 292 * pApplicationHandlerData also needs to be static in memory since no malloc are performed by the SDK
JMF 0:082731ede69f 293 *
JMF 0:082731ede69f 294 * @return An IoT Error Type defining successful/failed subscription
JMF 0:082731ede69f 295 */
JMF 0:082731ede69f 296 IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen,
JMF 0:082731ede69f 297 QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData) {
JMF 0:082731ede69f 298 ClientState clientState;
JMF 0:082731ede69f 299 IoT_Error_t rc, subRc;
JMF 0:082731ede69f 300
JMF 0:082731ede69f 301 FUNC_ENTRY;
JMF 0:082731ede69f 302
JMF 0:082731ede69f 303 if(NULL == pClient || NULL == pTopicName || NULL == pApplicationHandler) {
JMF 0:082731ede69f 304 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 305 }
JMF 0:082731ede69f 306
JMF 0:082731ede69f 307 if(!aws_iot_mqtt_is_client_connected(pClient)) {
JMF 0:082731ede69f 308 FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR);
JMF 0:082731ede69f 309 }
JMF 0:082731ede69f 310
JMF 0:082731ede69f 311 clientState = aws_iot_mqtt_get_client_state(pClient);
JMF 0:082731ede69f 312 if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) {
JMF 0:082731ede69f 313 FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR);
JMF 0:082731ede69f 314 }
JMF 0:082731ede69f 315
JMF 0:082731ede69f 316 rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS);
JMF 0:082731ede69f 317 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 318 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 319 }
JMF 0:082731ede69f 320
JMF 0:082731ede69f 321 subRc = _aws_iot_mqtt_internal_subscribe(pClient, pTopicName, topicNameLen, qos,
JMF 0:082731ede69f 322 pApplicationHandler, pApplicationHandlerData);
JMF 0:082731ede69f 323
JMF 0:082731ede69f 324 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS, clientState);
JMF 0:082731ede69f 325 if(AWS_SUCCESS == subRc && AWS_SUCCESS != rc) {
JMF 0:082731ede69f 326 subRc = rc;
JMF 0:082731ede69f 327 }
JMF 0:082731ede69f 328
JMF 0:082731ede69f 329 FUNC_EXIT_RC(subRc);
JMF 0:082731ede69f 330 }
JMF 0:082731ede69f 331
JMF 0:082731ede69f 332 /**
JMF 0:082731ede69f 333 * @brief Subscribe to an MQTT topic.
JMF 0:082731ede69f 334 *
JMF 0:082731ede69f 335 * Called to send a subscribe message to the broker requesting a subscription
JMF 0:082731ede69f 336 * to an MQTT topic.
JMF 0:082731ede69f 337 * This is the internal function which is called by the resubscribe API to perform the operation.
JMF 0:082731ede69f 338 * Not meant to be called directly as it doesn't do validations or client state changes
JMF 0:082731ede69f 339 * @note Call is blocking. The call returns after the receipt of the SUBACK control packet.
JMF 0:082731ede69f 340 *
JMF 0:082731ede69f 341 * @param pClient Reference to the IoT Client
JMF 0:082731ede69f 342 *
JMF 0:082731ede69f 343 * @return An IoT Error Type defining successful/failed subscription
JMF 0:082731ede69f 344 */
JMF 0:082731ede69f 345 static IoT_Error_t _aws_iot_mqtt_internal_resubscribe(AWS_IoT_Client *pClient) {
JMF 0:082731ede69f 346 uint16_t packetId;
JMF 0:082731ede69f 347 uint32_t len, count, existingSubCount, itr;
JMF 0:082731ede69f 348 IoT_Error_t rc;
JMF 0:082731ede69f 349 awsTimer timer;
JMF 0:082731ede69f 350 QoS grantedQoS[3] = {QOS0, QOS0, QOS0};
JMF 0:082731ede69f 351
JMF 0:082731ede69f 352 FUNC_ENTRY;
JMF 0:082731ede69f 353
JMF 0:082731ede69f 354 packetId = 0;
JMF 0:082731ede69f 355 len = 0;
JMF 0:082731ede69f 356 count = 0;
JMF 0:082731ede69f 357 existingSubCount = _aws_iot_mqtt_get_free_message_handler_index(pClient);
JMF 0:082731ede69f 358
JMF 0:082731ede69f 359 for(itr = 0; itr < existingSubCount; itr++) {
JMF 0:082731ede69f 360 if(pClient->clientData.messageHandlers[itr].topicName == NULL) {
JMF 0:082731ede69f 361 continue;
JMF 0:082731ede69f 362 }
JMF 0:082731ede69f 363
JMF 0:082731ede69f 364 init_timer(&timer);
JMF 0:082731ede69f 365 countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
JMF 0:082731ede69f 366
JMF 0:082731ede69f 367 rc = _aws_iot_mqtt_serialize_subscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0,
JMF 0:082731ede69f 368 aws_iot_mqtt_get_next_packet_id(pClient), 1,
JMF 0:082731ede69f 369 &(pClient->clientData.messageHandlers[itr].topicName),
JMF 0:082731ede69f 370 &(pClient->clientData.messageHandlers[itr].topicNameLen),
JMF 0:082731ede69f 371 &(pClient->clientData.messageHandlers[itr].qos), &len);
JMF 0:082731ede69f 372 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 373 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 374 }
JMF 0:082731ede69f 375
JMF 0:082731ede69f 376 /* send the subscribe packet */
JMF 0:082731ede69f 377 rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer);
JMF 0:082731ede69f 378 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 379 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 380 }
JMF 0:082731ede69f 381
JMF 0:082731ede69f 382 /* wait for suback */
JMF 0:082731ede69f 383 rc = aws_iot_mqtt_internal_wait_for_read(pClient, SUBACK, &timer);
JMF 0:082731ede69f 384 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 385 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 386 }
JMF 0:082731ede69f 387
JMF 0:082731ede69f 388 /* Granted QoS can be 0, 1 or 2 */
JMF 0:082731ede69f 389 rc = _aws_iot_mqtt_deserialize_suback(&packetId, 1, &count, grantedQoS, pClient->clientData.readBuf,
JMF 0:082731ede69f 390 pClient->clientData.readBufSize);
JMF 0:082731ede69f 391 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 392 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 393 }
JMF 0:082731ede69f 394 }
JMF 0:082731ede69f 395
JMF 0:082731ede69f 396 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 397 }
JMF 0:082731ede69f 398
JMF 0:082731ede69f 399 /**
JMF 0:082731ede69f 400 * @brief Subscribe to an MQTT topic.
JMF 0:082731ede69f 401 *
JMF 0:082731ede69f 402 * Called to send a subscribe message to the broker requesting a subscription
JMF 0:082731ede69f 403 * to an MQTT topic.
JMF 0:082731ede69f 404 * This is the outer function which does the validations and calls the internal resubscribe above
JMF 0:082731ede69f 405 * to perform the actual operation. It is also responsible for client state changes
JMF 0:082731ede69f 406 * @note Call is blocking. The call returns after the receipt of the SUBACK control packet.
JMF 0:082731ede69f 407 *
JMF 0:082731ede69f 408 * @param pClient Reference to the IoT Client
JMF 0:082731ede69f 409 *
JMF 0:082731ede69f 410 * @return An IoT Error Type defining successful/failed subscription
JMF 0:082731ede69f 411 */
JMF 0:082731ede69f 412 IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) {
JMF 0:082731ede69f 413 IoT_Error_t rc, resubRc;
JMF 0:082731ede69f 414
JMF 0:082731ede69f 415 FUNC_ENTRY;
JMF 0:082731ede69f 416
JMF 0:082731ede69f 417 if(NULL == pClient) {
JMF 0:082731ede69f 418 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 419 }
JMF 0:082731ede69f 420
JMF 0:082731ede69f 421 if(false == aws_iot_mqtt_is_client_connected(pClient)) {
JMF 0:082731ede69f 422 FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR);
JMF 0:082731ede69f 423 }
JMF 0:082731ede69f 424
JMF 0:082731ede69f 425 if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) {
JMF 0:082731ede69f 426 FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR);
JMF 0:082731ede69f 427 }
JMF 0:082731ede69f 428
JMF 0:082731ede69f 429 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE,
JMF 0:082731ede69f 430 CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS);
JMF 0:082731ede69f 431 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 432 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 433 }
JMF 0:082731ede69f 434
JMF 0:082731ede69f 435 resubRc = _aws_iot_mqtt_internal_resubscribe(pClient);
JMF 0:082731ede69f 436
JMF 0:082731ede69f 437 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS,
JMF 0:082731ede69f 438 CLIENT_STATE_CONNECTED_IDLE);
JMF 0:082731ede69f 439 if(AWS_SUCCESS == resubRc && AWS_SUCCESS != rc) {
JMF 0:082731ede69f 440 resubRc = rc;
JMF 0:082731ede69f 441 }
JMF 0:082731ede69f 442
JMF 0:082731ede69f 443 FUNC_EXIT_RC(resubRc);
JMF 0:082731ede69f 444 }
JMF 0:082731ede69f 445
JMF 0:082731ede69f 446 #ifdef __cplusplus
JMF 0:082731ede69f 447 }
JMF 0:082731ede69f 448 #endif
JMF 0:082731ede69f 449