Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
aws_iot_mqtt_client_unsubscribe.c
00001 /* 00002 * Copyright 2015-2016 Amazon.com, Inc. or its affiliates. All Rights Reserved. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"). 00005 * You may not use this file except in compliance with the License. 00006 * A copy of the License is located at 00007 * 00008 * http://aws.amazon.com/apache2.0 00009 * 00010 * or in the "license" file accompanying this file. This file is distributed 00011 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 00012 * express or implied. See the License for the specific language governing 00013 * permissions and limitations under the License. 00014 */ 00015 00016 // Based on Eclipse Paho. 00017 /******************************************************************************* 00018 * Copyright (c) 2014 IBM Corp. 00019 * 00020 * All rights reserved. This program and the accompanying materials 00021 * are made available under the terms of the Eclipse Public License v1.0 00022 * and Eclipse Distribution License v1.0 which accompany this distribution. 00023 * 00024 * The Eclipse Public License is available at 00025 * http://www.eclipse.org/legal/epl-v10.html 00026 * and the Eclipse Distribution License is available at 00027 * http://www.eclipse.org/org/documents/edl-v10.php. 00028 * 00029 * Contributors: 00030 * Ian Craggs - initial API and implementation and/or initial documentation 00031 *******************************************************************************/ 00032 00033 /** 00034 * @file aws_iot_mqtt_client_unsubscribe.c 00035 * @brief MQTT client unsubscribe API definitions 00036 */ 00037 00038 #ifdef __cplusplus 00039 extern "C" { 00040 #endif 00041 00042 #include "aws_iot_mqtt_client_common_internal.h" 00043 00044 /** 00045 * Serializes the supplied unsubscribe data into the supplied buffer, ready for sending 00046 * @param pTxBuf the raw buffer data, of the correct length determined by the remaining length field 00047 * @param txBufLen the length in bytes of the data in the supplied buffer 00048 * @param dup integer - the MQTT dup flag 00049 * @param packetId integer - the MQTT packet identifier 00050 * @param count - number of members in the topicFilters array 00051 * @param pTopicNameList - array of topic filter names 00052 * @param pTopicNameLenList - array of length of topic filter names in pTopicNameList 00053 * @param pSerializedLen - the length of the serialized data 00054 * @return IoT_Error_t indicating function execution status 00055 */ 00056 static IoT_Error_t _aws_iot_mqtt_serialize_unsubscribe(unsigned char *pTxBuf, size_t txBufLen, 00057 uint8_t dup, uint16_t packetId, 00058 uint32_t count, const char **pTopicNameList, 00059 uint16_t *pTopicNameLenList, uint32_t *pSerializedLen) { 00060 unsigned char *ptr = pTxBuf; 00061 uint32_t i = 0; 00062 uint32_t rem_len = 2; /* packetId */ 00063 IoT_Error_t rc; 00064 MQTTHeader header = {0}; 00065 00066 FUNC_ENTRY; 00067 00068 for(i = 0; i < count; ++i) { 00069 rem_len += (uint32_t) (pTopicNameLenList[i] + 2); /* topic + length */ 00070 } 00071 00072 if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) { 00073 FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR); 00074 } 00075 00076 rc = aws_iot_mqtt_internal_init_header(&header, UNSUBSCRIBE, QOS1, dup, 0); 00077 if(AWS_SUCCESS != rc) { 00078 FUNC_EXIT_RC(rc); 00079 } 00080 aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */ 00081 00082 ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */ 00083 00084 aws_iot_mqtt_internal_write_uint_16(&ptr, packetId); 00085 00086 for(i = 0; i < count; ++i) { 00087 aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicNameList[i], pTopicNameLenList[i]); 00088 } 00089 00090 *pSerializedLen = (uint32_t) (ptr - pTxBuf); 00091 00092 FUNC_EXIT_RC(AWS_SUCCESS); 00093 } 00094 00095 00096 /** 00097 * Deserializes the supplied (wire) buffer into unsuback data 00098 * @param pPacketId returned integer - the MQTT packet identifier 00099 * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field 00100 * @param rxBufLen the length in bytes of the data in the supplied buffer 00101 * @return IoT_Error_t indicating function execution status 00102 */ 00103 static IoT_Error_t _aws_iot_mqtt_deserialize_unsuback(uint16_t *pPacketId, unsigned char *pRxBuf, size_t rxBufLen) { 00104 unsigned char type = 0; 00105 unsigned char dup = 0; 00106 IoT_Error_t rc; 00107 00108 FUNC_ENTRY; 00109 00110 rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, pPacketId, pRxBuf, rxBufLen); 00111 if(AWS_SUCCESS == rc && UNSUBACK != type) { 00112 rc = FAILURE; 00113 } 00114 00115 FUNC_EXIT_RC(rc); 00116 } 00117 00118 /** 00119 * @brief Unsubscribe to an MQTT topic. 00120 * 00121 * Called to send an unsubscribe message to the broker requesting removal of a subscription 00122 * to an MQTT topic. 00123 * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. 00124 * This is the internal function which is called by the unsubscribe API to perform the operation. 00125 * Not meant to be called directly as it doesn't do validations or client state changes 00126 * 00127 * @param pClient Reference to the IoT Client 00128 * @param pTopicName Topic Name to publish to 00129 * @param topicNameLen Length of the topic name 00130 * 00131 * @return An IoT Error Type defining successful/failed unsubscribe call 00132 */ 00133 static IoT_Error_t _aws_iot_mqtt_internal_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, 00134 uint16_t topicFilterLen) { 00135 /* No NULL checks because this is a static internal function */ 00136 00137 awsTimer timer; 00138 00139 uint16_t packet_id; 00140 uint32_t serializedLen = 0; 00141 uint32_t i = 0; 00142 IoT_Error_t rc; 00143 bool subscriptionExists = false; 00144 00145 FUNC_ENTRY; 00146 00147 /* Remove from message handler array */ 00148 for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { 00149 if(pClient->clientData.messageHandlers[i].topicName != NULL && 00150 (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { 00151 subscriptionExists = true; 00152 break; 00153 } 00154 } 00155 00156 if(false == subscriptionExists) { 00157 FUNC_EXIT_RC(FAILURE); 00158 } 00159 00160 init_timer(&timer); 00161 countdown_ms(&timer, pClient->clientData.commandTimeoutMs); 00162 00163 rc = _aws_iot_mqtt_serialize_unsubscribe(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0, 00164 aws_iot_mqtt_get_next_packet_id(pClient), 1, &pTopicFilter, 00165 &topicFilterLen, &serializedLen); 00166 if(AWS_SUCCESS != rc) { 00167 FUNC_EXIT_RC(rc); 00168 } 00169 00170 /* send the unsubscribe packet */ 00171 rc = aws_iot_mqtt_internal_send_packet(pClient, serializedLen, &timer); 00172 if(AWS_SUCCESS != rc) { 00173 FUNC_EXIT_RC(rc); 00174 } 00175 00176 rc = aws_iot_mqtt_internal_wait_for_read(pClient, UNSUBACK, &timer); 00177 if(AWS_SUCCESS != rc) { 00178 FUNC_EXIT_RC(rc); 00179 } 00180 00181 rc = _aws_iot_mqtt_deserialize_unsuback(&packet_id, pClient->clientData.readBuf, pClient->clientData.readBufSize); 00182 if(AWS_SUCCESS != rc) { 00183 FUNC_EXIT_RC(rc); 00184 } 00185 00186 /* Remove from message handler array */ 00187 for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { 00188 if(pClient->clientData.messageHandlers[i].topicName != NULL && 00189 (strcmp(pClient->clientData.messageHandlers[i].topicName, pTopicFilter) == 0)) { 00190 pClient->clientData.messageHandlers[i].topicName = NULL; 00191 /* We don't want to break here, in case the same topic is registered 00192 * with 2 callbacks. Unlikely scenario */ 00193 } 00194 } 00195 00196 FUNC_EXIT_RC(AWS_SUCCESS); 00197 } 00198 00199 /** 00200 * @brief Unsubscribe to an MQTT topic. 00201 * 00202 * Called to send an unsubscribe message to the broker requesting removal of a subscription 00203 * to an MQTT topic. 00204 * @note Call is blocking. The call returns after the receipt of the UNSUBACK control packet. 00205 * This is the outer function which does the validations and calls the internal unsubscribe above 00206 * to perform the actual operation. It is also responsible for client state changes 00207 * 00208 * @param pClient Reference to the IoT Client 00209 * @param pTopicName Topic Name to publish to 00210 * @param topicNameLen Length of the topic name 00211 * 00212 * @return An IoT Error Type defining successful/failed unsubscribe call 00213 */ 00214 IoT_Error_t aws_iot_mqtt_unsubscribe(AWS_IoT_Client *pClient, const char *pTopicFilter, uint16_t topicFilterLen) { 00215 IoT_Error_t rc, unsubRc; 00216 ClientState clientState; 00217 00218 if(NULL == pClient || NULL == pTopicFilter) { 00219 return NULL_VALUE_ERROR; 00220 } 00221 00222 if(!aws_iot_mqtt_is_client_connected(pClient)) { 00223 return NETWORK_DISCONNECTED_ERROR; 00224 } 00225 00226 clientState = aws_iot_mqtt_get_client_state(pClient); 00227 if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { 00228 return MQTT_CLIENT_NOT_IDLE_ERROR; 00229 } 00230 00231 rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS); 00232 if(AWS_SUCCESS != rc) { 00233 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); 00234 return rc; 00235 } 00236 00237 unsubRc = _aws_iot_mqtt_internal_unsubscribe(pClient, pTopicFilter, topicFilterLen); 00238 00239 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS, clientState); 00240 if(AWS_SUCCESS == unsubRc && AWS_SUCCESS != rc) { 00241 unsubRc = rc; 00242 } 00243 00244 return unsubRc; 00245 } 00246 00247 #ifdef __cplusplus 00248 } 00249 #endif 00250
Generated on Tue Jul 12 2022 19:02:38 by
1.7.2