test

Committer:
peyo
Date:
Wed Apr 12 14:07:09 2017 +0200
Revision:
0:cd5404401c2f
first commit

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_unsubscribe.c
peyo 0:cd5404401c2f 35 * @brief MQTT client unsubscribe 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 unsubscribe data into the supplied buffer, ready for sending
peyo 0:cd5404401c2f 46 * @param pTxBuf the raw buffer data, of the correct length determined by the remaining length field
peyo 0:cd5404401c2f 47 * @param txBufLen the length in bytes of the data in the supplied buffer
peyo 0:cd5404401c2f 48 * @param dup integer - the MQTT dup flag
peyo 0:cd5404401c2f 49 * @param packetId integer - the MQTT packet identifier
peyo 0:cd5404401c2f 50 * @param count - number of members in the topicFilters array
peyo 0:cd5404401c2f 51 * @param pTopicNameList - array of topic filter names
peyo 0:cd5404401c2f 52 * @param pTopicNameLenList - array of length of topic filter names in pTopicNameList
peyo 0:cd5404401c2f 53 * @param pSerializedLen - the length of the serialized data
peyo 0:cd5404401c2f 54 * @return IoT_Error_t indicating function execution status
peyo 0:cd5404401c2f 55 */
peyo 0:cd5404401c2f 56 static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, size_t txBufLen,
peyo 0:cd5404401c2f 57 uint8_t dup, uint16_t packetId,
peyo 0:cd5404401c2f 58 uint32_t count, const char **pTopicNameList,
peyo 0:cd5404401c2f 59 uint16_t *pTopicNameLenList, uint32_t *pSerializedLen) {
peyo 0:cd5404401c2f 60 unsigned char *ptr = pTxBuf;
peyo 0:cd5404401c2f 61 uint32_t i = 0;
peyo 0:cd5404401c2f 62 uint32_t rem_len = 2; /* packetId */
peyo 0:cd5404401c2f 63 IoT_Error_t rc;
peyo 0:cd5404401c2f 64 MQTTHeader header = {0};
peyo 0:cd5404401c2f 65
peyo 0:cd5404401c2f 66 FUNC_ENTRY;
peyo 0:cd5404401c2f 67
peyo 0:cd5404401c2f 68 for(i = 0; i < count; ++i) {
peyo 0:cd5404401c2f 69 rem_len += (uint32_t) (pTopicNameLenList[i] + 2); /* topic + length */
peyo 0:cd5404401c2f 70 }
peyo 0:cd5404401c2f 71
peyo 0:cd5404401c2f 72 if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) {
peyo 0:cd5404401c2f 73 FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR);
peyo 0:cd5404401c2f 74 }
peyo 0:cd5404401c2f 75
peyo 0:cd5404401c2f 76 rc = aws_iot_mqtt_internal_init_header(&header, UNSUBSCRIBE, QOS1, dup, 0);
peyo 0:cd5404401c2f 77 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 78 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 79 }
peyo 0:cd5404401c2f 80 aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */
peyo 0:cd5404401c2f 81
peyo 0:cd5404401c2f 82 ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */
peyo 0:cd5404401c2f 83
peyo 0:cd5404401c2f 84 aws_iot_mqtt_internal_write_uint_16(&ptr, packetId);
peyo 0:cd5404401c2f 85
peyo 0:cd5404401c2f 86 for(i = 0; i < count; ++i) {
peyo 0:cd5404401c2f 87 aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[i], pTopicNameLenList[i]);
peyo 0:cd5404401c2f 88 }
peyo 0:cd5404401c2f 89
peyo 0:cd5404401c2f 90 *pSerializedLen = (uint32_t) (ptr - pTxBuf);
peyo 0:cd5404401c2f 91
peyo 0:cd5404401c2f 92 FUNC_EXIT_RC(SUCCESS);
peyo 0:cd5404401c2f 93 }
peyo 0:cd5404401c2f 94
peyo 0:cd5404401c2f 95
peyo 0:cd5404401c2f 96 /**
peyo 0:cd5404401c2f 97 * Deserializes the supplied (wire) buffer into unsuback data
peyo 0:cd5404401c2f 98 * @param pPacketId returned integer - the MQTT packet identifier
peyo 0:cd5404401c2f 99 * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field
peyo 0:cd5404401c2f 100 * @param rxBufLen the length in bytes of the data in the supplied buffer
peyo 0:cd5404401c2f 101 * @return IoT_Error_t indicating function execution status
peyo 0:cd5404401c2f 102 */
peyo 0:cd5404401c2f 103 static IoT_Error_t _aws_iot_mqtt_deserialize_unsuback(uint16_t *pPacketId, unsigned char *pRxBuf, size_t rxBufLen) {
peyo 0:cd5404401c2f 104 unsigned char type = 0;
peyo 0:cd5404401c2f 105 unsigned char dup = 0;
peyo 0:cd5404401c2f 106 IoT_Error_t rc;
peyo 0:cd5404401c2f 107
peyo 0:cd5404401c2f 108 FUNC_ENTRY;
peyo 0:cd5404401c2f 109
peyo 0:cd5404401c2f 110 rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, pPacketId, pRxBuf, rxBufLen);
peyo 0:cd5404401c2f 111 if(SUCCESS == rc && UNSUBACK != type) {
peyo 0:cd5404401c2f 112 rc = FAILURE;
peyo 0:cd5404401c2f 113 }
peyo 0:cd5404401c2f 114
peyo 0:cd5404401c2f 115 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 116 }
peyo 0:cd5404401c2f 117
peyo 0:cd5404401c2f 118 /**
peyo 0:cd5404401c2f 119 * @brief Unsubscribe to an MQTT topic.
peyo 0:cd5404401c2f 120 *
peyo 0:cd5404401c2f 121 * Called to send an unsubscribe message to the broker requesting removal of a subscription
peyo 0:cd5404401c2f 122 * to an MQTT topic.
peyo 0:cd5404401c2f 123 * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet.
peyo 0:cd5404401c2f 124 * This is the internal function which is called by the unsubscribe API to perform the operation.
peyo 0:cd5404401c2f 125 * Not meant to be called directly as it doesn't do validations or client state changes
peyo 0:cd5404401c2f 126 *
peyo 0:cd5404401c2f 127 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 128 * @param pTopicName Topic Name to publish to
peyo 0:cd5404401c2f 129 * @param topicNameLen Length of the topic name
peyo 0:cd5404401c2f 130 *
peyo 0:cd5404401c2f 131 * @return An IoT Error Type defining successful/failed unsubscribe call
peyo 0:cd5404401c2f 132 */
peyo 0:cd5404401c2f 133 static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter,
peyo 0:cd5404401c2f 134 uint16_t topicFilterLen) {
peyo 0:cd5404401c2f 135 /* No NULL checks because this is a static internal function */
peyo 0:cd5404401c2f 136
peyo 0:cd5404401c2f 137 TimerAWS timer;
peyo 0:cd5404401c2f 138
peyo 0:cd5404401c2f 139 uint16_t packet_id;
peyo 0:cd5404401c2f 140 uint32_t serializedLen = 0;
peyo 0:cd5404401c2f 141 uint32_t i = 0;
peyo 0:cd5404401c2f 142 IoT_Error_t rc;
peyo 0:cd5404401c2f 143 bool subscriptionExists = false;
peyo 0:cd5404401c2f 144
peyo 0:cd5404401c2f 145 FUNC_ENTRY;
peyo 0:cd5404401c2f 146
peyo 0:cd5404401c2f 147 /* Remove from message handler array */
peyo 0:cd5404401c2f 148 for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) {
peyo 0:cd5404401c2f 149 if(pClient->clientData.messageHandlers[i].topicName != NULL &&
peyo 0:cd5404401c2f 150 (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) {
peyo 0:cd5404401c2f 151 subscriptionExists = true;
peyo 0:cd5404401c2f 152 }
peyo 0:cd5404401c2f 153 }
peyo 0:cd5404401c2f 154
peyo 0:cd5404401c2f 155 if(false == subscriptionExists) {
peyo 0:cd5404401c2f 156 FUNC_EXIT_RC(FAILURE);
peyo 0:cd5404401c2f 157 }
peyo 0:cd5404401c2f 158
peyo 0:cd5404401c2f 159 init_timer(&timer);
peyo 0:cd5404401c2f 160 countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
peyo 0:cd5404401c2f 161
peyo 0:cd5404401c2f 162 rc = _aws_iot_mqtt_serialize_unsubscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0,
peyo 0:cd5404401c2f 163 aws_iot_mqtt_get_next_packet_id(pClient), 1, &pTopicFilter,
peyo 0:cd5404401c2f 164 &topicFilterLen, &serializedLen);
peyo 0:cd5404401c2f 165 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 166 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 167 }
peyo 0:cd5404401c2f 168
peyo 0:cd5404401c2f 169 /* send the unsubscribe packet */
peyo 0:cd5404401c2f 170 rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer);
peyo 0:cd5404401c2f 171 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 172 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 173 }
peyo 0:cd5404401c2f 174
peyo 0:cd5404401c2f 175 rc = aws_iot_mqtt_internal_wait_for_read(pClient, UNSUBACK, &timer);
peyo 0:cd5404401c2f 176 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 177 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 178 }
peyo 0:cd5404401c2f 179
peyo 0:cd5404401c2f 180 rc = _aws_iot_mqtt_deserialize_unsuback(&packet_id, pClient->clientData.readBuf, pClient->clientData.readBufSize);
peyo 0:cd5404401c2f 181 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 182 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 183 }
peyo 0:cd5404401c2f 184
peyo 0:cd5404401c2f 185 /* Remove from message handler array */
peyo 0:cd5404401c2f 186 for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) {
peyo 0:cd5404401c2f 187 if(pClient->clientData.messageHandlers[i].topicName != NULL &&
peyo 0:cd5404401c2f 188 (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) {
peyo 0:cd5404401c2f 189 pClient->clientData.messageHandlers[i].topicName = NULL;
peyo 0:cd5404401c2f 190 /* We don't want to break here, in case the same topic is registered
peyo 0:cd5404401c2f 191 * with 2 callbacks. Unlikely scenario */
peyo 0:cd5404401c2f 192 }
peyo 0:cd5404401c2f 193 }
peyo 0:cd5404401c2f 194
peyo 0:cd5404401c2f 195 FUNC_EXIT_RC(SUCCESS);
peyo 0:cd5404401c2f 196 }
peyo 0:cd5404401c2f 197
peyo 0:cd5404401c2f 198 /**
peyo 0:cd5404401c2f 199 * @brief Unsubscribe to an MQTT topic.
peyo 0:cd5404401c2f 200 *
peyo 0:cd5404401c2f 201 * Called to send an unsubscribe message to the broker requesting removal of a subscription
peyo 0:cd5404401c2f 202 * to an MQTT topic.
peyo 0:cd5404401c2f 203 * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet.
peyo 0:cd5404401c2f 204 * This is the outer function which does the validations and calls the internal unsubscribe above
peyo 0:cd5404401c2f 205 * to perform the actual operation. It is also responsible for client state changes
peyo 0:cd5404401c2f 206 *
peyo 0:cd5404401c2f 207 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 208 * @param pTopicName Topic Name to publish to
peyo 0:cd5404401c2f 209 * @param topicNameLen Length of the topic name
peyo 0:cd5404401c2f 210 *
peyo 0:cd5404401c2f 211 * @return An IoT Error Type defining successful/failed unsubscribe call
peyo 0:cd5404401c2f 212 */
peyo 0:cd5404401c2f 213 IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen) {
peyo 0:cd5404401c2f 214 IoT_Error_t rc, unsubRc;
peyo 0:cd5404401c2f 215 ClientState clientState;
peyo 0:cd5404401c2f 216
peyo 0:cd5404401c2f 217 if(NULL == pClient || NULL == pTopicFilter) {
peyo 0:cd5404401c2f 218 return NULL_VALUE_ERROR;
peyo 0:cd5404401c2f 219 }
peyo 0:cd5404401c2f 220
peyo 0:cd5404401c2f 221 if(!aws_iot_mqtt_is_client_connected(pClient)) {
peyo 0:cd5404401c2f 222 return NETWORK_DISCONNECTED_ERROR;
peyo 0:cd5404401c2f 223 }
peyo 0:cd5404401c2f 224
peyo 0:cd5404401c2f 225 clientState = aws_iot_mqtt_get_client_state(pClient);
peyo 0:cd5404401c2f 226 if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) {
peyo 0:cd5404401c2f 227 return MQTT_CLIENT_NOT_IDLE_ERROR;
peyo 0:cd5404401c2f 228 }
peyo 0:cd5404401c2f 229
peyo 0:cd5404401c2f 230 rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS);
peyo 0:cd5404401c2f 231 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 232 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState);
peyo 0:cd5404401c2f 233 return rc;
peyo 0:cd5404401c2f 234 }
peyo 0:cd5404401c2f 235
peyo 0:cd5404401c2f 236 unsubRc = _aws_iot_mqtt_internal_unsubscribe(pClient, pTopicFilter, topicFilterLen);
peyo 0:cd5404401c2f 237
peyo 0:cd5404401c2f 238 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState);
peyo 0:cd5404401c2f 239 if(SUCCESS == unsubRc && SUCCESS != rc) {
peyo 0:cd5404401c2f 240 unsubRc = rc;
peyo 0:cd5404401c2f 241 }
peyo 0:cd5404401c2f 242
peyo 0:cd5404401c2f 243 return unsubRc;
peyo 0:cd5404401c2f 244 }
peyo 0:cd5404401c2f 245
peyo 0:cd5404401c2f 246 #ifdef __cplusplus
peyo 0:cd5404401c2f 247 }
peyo 0:cd5404401c2f 248 #endif
peyo 0:cd5404401c2f 249