test

Committer:
peyo
Date:
Wed Apr 12 14:09:46 2017 +0200
Revision:
1:3f75eb8d46f4
Parent:
0:cd5404401c2f
add main

Who changed what in which revision?

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