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 * Ian Craggs - fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=453144
JMF 0:082731ede69f 32 *******************************************************************************/
JMF 0:082731ede69f 33
JMF 0:082731ede69f 34 /**
JMF 0:082731ede69f 35 * @file aws_iot_mqtt_client_publish.c
JMF 0:082731ede69f 36 * @brief MQTT client publish API definitions
JMF 0:082731ede69f 37 */
JMF 0:082731ede69f 38
JMF 0:082731ede69f 39 #ifdef __cplusplus
JMF 0:082731ede69f 40 extern "C" {
JMF 0:082731ede69f 41 #endif
JMF 0:082731ede69f 42
JMF 0:082731ede69f 43 #include "aws_iot_mqtt_client_common_internal.h"
JMF 0:082731ede69f 44
JMF 0:082731ede69f 45 /**
JMF 0:082731ede69f 46 * @param stringVar pointer to the String into which the data is to be read
JMF 0:082731ede69f 47 * @param stringLen pointer to variable which has the length of the string
JMF 0:082731ede69f 48 * @param pptr pointer to the output buffer - incremented by the number of bytes used & returned
JMF 0:082731ede69f 49 * @param enddata pointer to the end of the data: do not read beyond
JMF 0:082731ede69f 50 * @return AWS_SUCCESS if successful, FAILURE if not
JMF 0:082731ede69f 51 */
JMF 0:082731ede69f 52 static IoT_Error_t _aws_iot_mqtt_read_string_with_len(char **stringVar, uint16_t *stringLen,
JMF 0:082731ede69f 53 unsigned char **pptr, unsigned char *enddata) {
JMF 0:082731ede69f 54 IoT_Error_t rc = FAILURE;
JMF 0:082731ede69f 55
JMF 0:082731ede69f 56 FUNC_ENTRY;
JMF 0:082731ede69f 57 /* the first two bytes are the length of the string */
JMF 0:082731ede69f 58 /* enough length to read the integer? */
JMF 0:082731ede69f 59 if(enddata - (*pptr) > 1) {
JMF 0:082731ede69f 60 *stringLen = aws_iot_mqtt_internal_read_uint16_t(pptr); /* increments pptr to point past length */
JMF 0:082731ede69f 61 if(&(*pptr)[*stringLen] <= enddata) {
JMF 0:082731ede69f 62 *stringVar = (char *) *pptr;
JMF 0:082731ede69f 63 *pptr += *stringLen;
JMF 0:082731ede69f 64 rc = AWS_SUCCESS;
JMF 0:082731ede69f 65 }
JMF 0:082731ede69f 66 }
JMF 0:082731ede69f 67
JMF 0:082731ede69f 68 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 69 }
JMF 0:082731ede69f 70
JMF 0:082731ede69f 71 /**
JMF 0:082731ede69f 72 * Serializes the supplied publish data into the supplied buffer, ready for sending
JMF 0:082731ede69f 73 * @param pTxBuf the buffer into which the packet will be serialized
JMF 0:082731ede69f 74 * @param txBufLen the length in bytes of the supplied buffer
JMF 0:082731ede69f 75 * @param dup uint8_t - the MQTT dup flag
JMF 0:082731ede69f 76 * @param qos QoS - the MQTT QoS value
JMF 0:082731ede69f 77 * @param retained uint8_t - the MQTT retained flag
JMF 0:082731ede69f 78 * @param packetId uint16_t - the MQTT packet identifier
JMF 0:082731ede69f 79 * @param pTopicName char * - the MQTT topic in the publish
JMF 0:082731ede69f 80 * @param topicNameLen uint16_t - the length of the Topic Name
JMF 0:082731ede69f 81 * @param pPayload byte buffer - the MQTT publish payload
JMF 0:082731ede69f 82 * @param payloadLen size_t - the length of the MQTT payload
JMF 0:082731ede69f 83 * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len
JMF 0:082731ede69f 84 *
JMF 0:082731ede69f 85 * @return An IoT Error Type defining successful/failed call
JMF 0:082731ede69f 86 */
JMF 0:082731ede69f 87 static IoT_Error_t _aws_iot_mqtt_internal_serialize_publish(unsigned char *pTxBuf, size_t txBufLen, uint8_t dup,
JMF 0:082731ede69f 88 QoS qos, uint8_t retained, uint16_t packetId,
JMF 0:082731ede69f 89 const char *pTopicName, uint16_t topicNameLen,
JMF 0:082731ede69f 90 const unsigned char *pPayload, size_t payloadLen,
JMF 0:082731ede69f 91 uint32_t *pSerializedLen) {
JMF 0:082731ede69f 92 unsigned char *ptr;
JMF 0:082731ede69f 93 uint32_t rem_len;
JMF 0:082731ede69f 94 IoT_Error_t rc;
JMF 0:082731ede69f 95 MQTTHeader header = {0};
JMF 0:082731ede69f 96
JMF 0:082731ede69f 97 FUNC_ENTRY;
JMF 0:082731ede69f 98 if(NULL == pTxBuf || NULL == pPayload || NULL == pSerializedLen) {
JMF 0:082731ede69f 99 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 100 }
JMF 0:082731ede69f 101
JMF 0:082731ede69f 102 ptr = pTxBuf;
JMF 0:082731ede69f 103 rem_len = 0;
JMF 0:082731ede69f 104
JMF 0:082731ede69f 105 rem_len += (uint32_t) (topicNameLen + payloadLen + 2);
JMF 0:082731ede69f 106 if(qos > 0) {
JMF 0:082731ede69f 107 rem_len += 2; /* packetId */
JMF 0:082731ede69f 108 }
JMF 0:082731ede69f 109 if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(rem_len) > txBufLen) {
JMF 0:082731ede69f 110 FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR);
JMF 0:082731ede69f 111 }
JMF 0:082731ede69f 112
JMF 0:082731ede69f 113 rc = aws_iot_mqtt_internal_init_header(&header, PUBLISH, qos, dup, retained);
JMF 0:082731ede69f 114 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 115 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 116 }
JMF 0:082731ede69f 117 aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */
JMF 0:082731ede69f 118
JMF 0:082731ede69f 119 ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, rem_len); /* write remaining length */;
JMF 0:082731ede69f 120
JMF 0:082731ede69f 121 aws_iot_mqtt_internal_write_utf8_string(&ptr, pTopicName, topicNameLen);
JMF 0:082731ede69f 122
JMF 0:082731ede69f 123 if(qos > 0) {
JMF 0:082731ede69f 124 aws_iot_mqtt_internal_write_uint_16(&ptr, packetId);
JMF 0:082731ede69f 125 }
JMF 0:082731ede69f 126
JMF 0:082731ede69f 127 memcpy(ptr, pPayload, payloadLen);
JMF 0:082731ede69f 128 ptr += payloadLen;
JMF 0:082731ede69f 129
JMF 0:082731ede69f 130 *pSerializedLen = (uint32_t) (ptr - pTxBuf);
JMF 0:082731ede69f 131
JMF 0:082731ede69f 132 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 133 }
JMF 0:082731ede69f 134
JMF 0:082731ede69f 135 /**
JMF 0:082731ede69f 136 * Serializes the ack packet into the supplied buffer.
JMF 0:082731ede69f 137 * @param pTxBuf the buffer into which the packet will be serialized
JMF 0:082731ede69f 138 * @param txBufLen the length in bytes of the supplied buffer
JMF 0:082731ede69f 139 * @param msgType the MQTT packet type
JMF 0:082731ede69f 140 * @param dup the MQTT dup flag
JMF 0:082731ede69f 141 * @param packetId the MQTT packet identifier
JMF 0:082731ede69f 142 * @param pSerializedLen uint32_t - pointer to the variable that stores serialized len
JMF 0:082731ede69f 143 *
JMF 0:082731ede69f 144 * @return An IoT Error Type defining successful/failed call
JMF 0:082731ede69f 145 */
JMF 0:082731ede69f 146 IoT_Error_t aws_iot_mqtt_internal_serialize_ack(unsigned char *pTxBuf, size_t txBufLen,
JMF 0:082731ede69f 147 MessageTypes msgType, uint8_t dup, uint16_t packetId,
JMF 0:082731ede69f 148 uint32_t *pSerializedLen) {
JMF 0:082731ede69f 149 unsigned char *ptr;
JMF 0:082731ede69f 150 QoS requestQoS;
JMF 0:082731ede69f 151 IoT_Error_t rc;
JMF 0:082731ede69f 152 MQTTHeader header = {0};
JMF 0:082731ede69f 153 FUNC_ENTRY;
JMF 0:082731ede69f 154 if(NULL == pTxBuf || pSerializedLen == NULL) {
JMF 0:082731ede69f 155 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 156 }
JMF 0:082731ede69f 157
JMF 0:082731ede69f 158 ptr = pTxBuf;
JMF 0:082731ede69f 159
JMF 0:082731ede69f 160 /* Minimum byte length required by ACK headers is
JMF 0:082731ede69f 161 * 2 for fixed and 2 for variable part */
JMF 0:082731ede69f 162 if(4 > txBufLen) {
JMF 0:082731ede69f 163 FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR);
JMF 0:082731ede69f 164 }
JMF 0:082731ede69f 165
JMF 0:082731ede69f 166 requestQoS = (PUBREL == msgType) ? QOS1 : QOS0;
JMF 0:082731ede69f 167 rc = aws_iot_mqtt_internal_init_header(&header, msgType, requestQoS, dup, 0);
JMF 0:082731ede69f 168 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 169 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 170 }
JMF 0:082731ede69f 171 aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */
JMF 0:082731ede69f 172
JMF 0:082731ede69f 173 ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, 2); /* write remaining length */
JMF 0:082731ede69f 174 aws_iot_mqtt_internal_write_uint_16(&ptr, packetId);
JMF 0:082731ede69f 175 *pSerializedLen = (uint32_t) (ptr - pTxBuf);
JMF 0:082731ede69f 176
JMF 0:082731ede69f 177 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 178 }
JMF 0:082731ede69f 179
JMF 0:082731ede69f 180 /**
JMF 0:082731ede69f 181 * @brief Publish an MQTT message on a topic
JMF 0:082731ede69f 182 *
JMF 0:082731ede69f 183 * Called to publish an MQTT message on a topic.
JMF 0:082731ede69f 184 * @note Call is blocking. In the case of a QoS 0 message the function returns
JMF 0:082731ede69f 185 * after the message was successfully passed to the TLS layer. In the case of QoS 1
JMF 0:082731ede69f 186 * the function returns after the receipt of the PUBACK control packet.
JMF 0:082731ede69f 187 * This is the internal function which is called by the publish API to perform the operation.
JMF 0:082731ede69f 188 * Not meant to be called directly as it doesn't do validations or client state changes
JMF 0:082731ede69f 189 *
JMF 0:082731ede69f 190 * @param pClient Reference to the IoT Client
JMF 0:082731ede69f 191 * @param pTopicName Topic Name to publish to
JMF 0:082731ede69f 192 * @param topicNameLen Length of the topic name
JMF 0:082731ede69f 193 * @param pParams Pointer to Publish Message parameters
JMF 0:082731ede69f 194 *
JMF 0:082731ede69f 195 * @return An IoT Error Type defining successful/failed publish
JMF 0:082731ede69f 196 */
JMF 0:082731ede69f 197 static IoT_Error_t _aws_iot_mqtt_internal_publish(AWS_IoT_Client *pClient, const char *pTopicName,
JMF 0:082731ede69f 198 uint16_t topicNameLen, IoT_Publish_Message_Params *pParams) {
JMF 0:082731ede69f 199 awsTimer timer;
JMF 0:082731ede69f 200 uint32_t len = 0;
JMF 0:082731ede69f 201 uint16_t packet_id;
JMF 0:082731ede69f 202 unsigned char dup, type;
JMF 0:082731ede69f 203 IoT_Error_t rc;
JMF 0:082731ede69f 204
JMF 0:082731ede69f 205 FUNC_ENTRY;
JMF 0:082731ede69f 206
JMF 0:082731ede69f 207 init_timer(&timer);
JMF 0:082731ede69f 208 countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
JMF 0:082731ede69f 209
JMF 0:082731ede69f 210 if(QOS1 == pParams->qos) {
JMF 0:082731ede69f 211 pParams->id = aws_iot_mqtt_get_next_packet_id(pClient);
JMF 0:082731ede69f 212 }
JMF 0:082731ede69f 213
JMF 0:082731ede69f 214 rc = _aws_iot_mqtt_internal_serialize_publish(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, 0,
JMF 0:082731ede69f 215 pParams->qos, pParams->isRetained, pParams->id, pTopicName,
JMF 0:082731ede69f 216 topicNameLen, (unsigned char *) pParams->payload,
JMF 0:082731ede69f 217 pParams->payloadLen, &len);
JMF 0:082731ede69f 218 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 219 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 220 }
JMF 0:082731ede69f 221
JMF 0:082731ede69f 222 /* send the publish packet */
JMF 0:082731ede69f 223 rc = aws_iot_mqtt_internal_send_packet(pClient, len, &timer);
JMF 0:082731ede69f 224 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 225 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 226 }
JMF 0:082731ede69f 227
JMF 0:082731ede69f 228 /* Wait for ack if QoS1 */
JMF 0:082731ede69f 229 if(QOS1 == pParams->qos) {
JMF 0:082731ede69f 230 rc = aws_iot_mqtt_internal_wait_for_read(pClient, PUBACK, &timer);
JMF 0:082731ede69f 231 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 232 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 233 }
JMF 0:082731ede69f 234
JMF 0:082731ede69f 235 rc = aws_iot_mqtt_internal_deserialize_ack(&type, &dup, &packet_id, pClient->clientData.readBuf,
JMF 0:082731ede69f 236 pClient->clientData.readBufSize);
JMF 0:082731ede69f 237 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 238 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 239 }
JMF 0:082731ede69f 240 }
JMF 0:082731ede69f 241
JMF 0:082731ede69f 242 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 243 }
JMF 0:082731ede69f 244
JMF 0:082731ede69f 245 /**
JMF 0:082731ede69f 246 * @brief Publish an MQTT message on a topic
JMF 0:082731ede69f 247 *
JMF 0:082731ede69f 248 * Called to publish an MQTT message on a topic.
JMF 0:082731ede69f 249 * @note Call is blocking. In the case of a QoS 0 message the function returns
JMF 0:082731ede69f 250 * after the message was successfully passed to the TLS layer. In the case of QoS 1
JMF 0:082731ede69f 251 * the function returns after the receipt of the PUBACK control packet.
JMF 0:082731ede69f 252 * This is the outer function which does the validations and calls the internal publish above
JMF 0:082731ede69f 253 * to perform the actual operation. It is also responsible for client state changes
JMF 0:082731ede69f 254 *
JMF 0:082731ede69f 255 * @param pClient Reference to the IoT Client
JMF 0:082731ede69f 256 * @param pTopicName Topic Name to publish to
JMF 0:082731ede69f 257 * @param topicNameLen Length of the topic name
JMF 0:082731ede69f 258 * @param pParams Pointer to Publish Message parameters
JMF 0:082731ede69f 259 *
JMF 0:082731ede69f 260 * @return An IoT Error Type defining successful/failed publish
JMF 0:082731ede69f 261 */
JMF 0:082731ede69f 262 IoT_Error_t aws_iot_mqtt_publish(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen,
JMF 0:082731ede69f 263 IoT_Publish_Message_Params *pParams) {
JMF 0:082731ede69f 264 IoT_Error_t rc, pubRc;
JMF 0:082731ede69f 265 ClientState clientState;
JMF 0:082731ede69f 266
JMF 0:082731ede69f 267 FUNC_ENTRY;
JMF 0:082731ede69f 268
JMF 0:082731ede69f 269 if(NULL == pClient || NULL == pTopicName || 0 == topicNameLen || NULL == pParams) {
JMF 0:082731ede69f 270 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 271 }
JMF 0:082731ede69f 272
JMF 0:082731ede69f 273 if(!aws_iot_mqtt_is_client_connected(pClient)) {
JMF 0:082731ede69f 274 FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR);
JMF 0:082731ede69f 275 }
JMF 0:082731ede69f 276
JMF 0:082731ede69f 277 clientState = aws_iot_mqtt_get_client_state(pClient);
JMF 0:082731ede69f 278 if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) {
JMF 0:082731ede69f 279 FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR);
JMF 0:082731ede69f 280 }
JMF 0:082731ede69f 281
JMF 0:082731ede69f 282 rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS);
JMF 0:082731ede69f 283 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 284 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 285 }
JMF 0:082731ede69f 286
JMF 0:082731ede69f 287 pubRc = _aws_iot_mqtt_internal_publish(pClient, pTopicName, topicNameLen, pParams);
JMF 0:082731ede69f 288
JMF 0:082731ede69f 289 rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS, clientState);
JMF 0:082731ede69f 290 if(AWS_SUCCESS == pubRc && AWS_SUCCESS != rc) {
JMF 0:082731ede69f 291 pubRc = rc;
JMF 0:082731ede69f 292 }
JMF 0:082731ede69f 293
JMF 0:082731ede69f 294 FUNC_EXIT_RC(pubRc);
JMF 0:082731ede69f 295 }
JMF 0:082731ede69f 296
JMF 0:082731ede69f 297 /**
JMF 0:082731ede69f 298 * Deserializes the supplied (wire) buffer into publish data
JMF 0:082731ede69f 299 * @param dup returned uint8_t - the MQTT dup flag
JMF 0:082731ede69f 300 * @param qos returned QoS type - the MQTT QoS value
JMF 0:082731ede69f 301 * @param retained returned uint8_t - the MQTT retained flag
JMF 0:082731ede69f 302 * @param pPacketId returned uint16_t - the MQTT packet identifier
JMF 0:082731ede69f 303 * @param pTopicName returned String - the MQTT topic in the publish
JMF 0:082731ede69f 304 * @param topicNameLen returned uint16_t - the length of the MQTT topic in the publish
JMF 0:082731ede69f 305 * @param payload returned byte buffer - the MQTT publish payload
JMF 0:082731ede69f 306 * @param payloadlen returned size_t - the length of the MQTT payload
JMF 0:082731ede69f 307 * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field
JMF 0:082731ede69f 308 * @param rxBufLen the length in bytes of the data in the supplied buffer
JMF 0:082731ede69f 309 *
JMF 0:082731ede69f 310 * @return An IoT Error Type defining successful/failed call
JMF 0:082731ede69f 311 */
JMF 0:082731ede69f 312 IoT_Error_t aws_iot_mqtt_internal_deserialize_publish(uint8_t *dup, QoS *qos,
JMF 0:082731ede69f 313 uint8_t *retained, uint16_t *pPacketId,
JMF 0:082731ede69f 314 char **pTopicName, uint16_t *topicNameLen,
JMF 0:082731ede69f 315 unsigned char **payload, size_t *payloadLen,
JMF 0:082731ede69f 316 unsigned char *pRxBuf, size_t rxBufLen) {
JMF 0:082731ede69f 317 unsigned char *curData = pRxBuf;
JMF 0:082731ede69f 318 unsigned char *endData = NULL;
JMF 0:082731ede69f 319 IoT_Error_t rc = FAILURE;
JMF 0:082731ede69f 320 uint32_t decodedLen = 0;
JMF 0:082731ede69f 321 uint32_t readBytesLen = 0;
JMF 0:082731ede69f 322 MQTTHeader header = {0};
JMF 0:082731ede69f 323
JMF 0:082731ede69f 324 FUNC_ENTRY;
JMF 0:082731ede69f 325
JMF 0:082731ede69f 326 if(NULL == dup || NULL == qos || NULL == retained || NULL == pPacketId) {
JMF 0:082731ede69f 327 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 328 }
JMF 0:082731ede69f 329
JMF 0:082731ede69f 330 /* Publish header size is at least four bytes.
JMF 0:082731ede69f 331 * Fixed header is two bytes.
JMF 0:082731ede69f 332 * Variable header size depends on QoS And Topic Name.
JMF 0:082731ede69f 333 * QoS level 0 doesn't have a message identifier (0 - 2 bytes)
JMF 0:082731ede69f 334 * Topic Name length fields decide size of topic name field (at least 2 bytes)
JMF 0:082731ede69f 335 * MQTT v3.1.1 Specification 3.3.1 */
JMF 0:082731ede69f 336 if(4 > rxBufLen) {
JMF 0:082731ede69f 337 FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
JMF 0:082731ede69f 338 }
JMF 0:082731ede69f 339
JMF 0:082731ede69f 340 header.byte = aws_iot_mqtt_internal_read_char(&curData);
JMF 0:082731ede69f 341 if(PUBLISH != MQTT_HEADER_FIELD_TYPE(header.byte)) {
JMF 0:082731ede69f 342 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 343 }
JMF 0:082731ede69f 344
JMF 0:082731ede69f 345 *dup = MQTT_HEADER_FIELD_DUP(header.byte);
JMF 0:082731ede69f 346 *qos = (QoS) MQTT_HEADER_FIELD_QOS(header.byte);
JMF 0:082731ede69f 347 *retained = MQTT_HEADER_FIELD_RETAIN(header.byte);
JMF 0:082731ede69f 348
JMF 0:082731ede69f 349 /* read remaining length */
JMF 0:082731ede69f 350 rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen);
JMF 0:082731ede69f 351 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 352 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 353 }
JMF 0:082731ede69f 354 curData += (readBytesLen);
JMF 0:082731ede69f 355 endData = curData + decodedLen;
JMF 0:082731ede69f 356
JMF 0:082731ede69f 357 /* do we have enough data to read the protocol version byte? */
JMF 0:082731ede69f 358 if(AWS_SUCCESS != _aws_iot_mqtt_read_string_with_len(pTopicName, topicNameLen, &curData, endData)
JMF 0:082731ede69f 359 || (0 > (endData - curData))) {
JMF 0:082731ede69f 360 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 361 }
JMF 0:082731ede69f 362
JMF 0:082731ede69f 363 if(QOS0 != *qos) {
JMF 0:082731ede69f 364 *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData);
JMF 0:082731ede69f 365 }
JMF 0:082731ede69f 366
JMF 0:082731ede69f 367 *payloadLen = (size_t) (endData - curData);
JMF 0:082731ede69f 368 *payload = curData;
JMF 0:082731ede69f 369
JMF 0:082731ede69f 370 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 371 }
JMF 0:082731ede69f 372
JMF 0:082731ede69f 373 /**
JMF 0:082731ede69f 374 * Deserializes the supplied (wire) buffer into an ack
JMF 0:082731ede69f 375 * @param pPacketType returned integer - the MQTT packet type
JMF 0:082731ede69f 376 * @param dup returned integer - the MQTT dup flag
JMF 0:082731ede69f 377 * @param pPacketId returned integer - the MQTT packet identifier
JMF 0:082731ede69f 378 * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field
JMF 0:082731ede69f 379 * @param rxBuflen the length in bytes of the data in the supplied buffer
JMF 0:082731ede69f 380 *
JMF 0:082731ede69f 381 * @return An IoT Error Type defining successful/failed call
JMF 0:082731ede69f 382 */
JMF 0:082731ede69f 383 IoT_Error_t aws_iot_mqtt_internal_deserialize_ack(unsigned char *pPacketType, unsigned char *dup,
JMF 0:082731ede69f 384 uint16_t *pPacketId, unsigned char *pRxBuf,
JMF 0:082731ede69f 385 size_t rxBuflen) {
JMF 0:082731ede69f 386 IoT_Error_t rc = FAILURE;
JMF 0:082731ede69f 387 unsigned char *curdata = pRxBuf;
JMF 0:082731ede69f 388 unsigned char *enddata = NULL;
JMF 0:082731ede69f 389 uint32_t decodedLen = 0;
JMF 0:082731ede69f 390 uint32_t readBytesLen = 0;
JMF 0:082731ede69f 391 MQTTHeader header = {0};
JMF 0:082731ede69f 392
JMF 0:082731ede69f 393 FUNC_ENTRY;
JMF 0:082731ede69f 394
JMF 0:082731ede69f 395 if(NULL == pPacketType || NULL == dup || NULL == pPacketId || NULL == pRxBuf) {
JMF 0:082731ede69f 396 FUNC_EXIT_RC(NULL_VALUE_ERROR);
JMF 0:082731ede69f 397 }
JMF 0:082731ede69f 398
JMF 0:082731ede69f 399 /* PUBACK fixed header size is two bytes, variable header is 2 bytes, MQTT v3.1.1 Specification 3.4.1 */
JMF 0:082731ede69f 400 if(4 > rxBuflen) {
JMF 0:082731ede69f 401 FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
JMF 0:082731ede69f 402 }
JMF 0:082731ede69f 403
JMF 0:082731ede69f 404
JMF 0:082731ede69f 405 header.byte = aws_iot_mqtt_internal_read_char(&curdata);
JMF 0:082731ede69f 406 *dup = MQTT_HEADER_FIELD_DUP(header.byte);
JMF 0:082731ede69f 407 *pPacketType = MQTT_HEADER_FIELD_TYPE(header.byte);
JMF 0:082731ede69f 408
JMF 0:082731ede69f 409 /* read remaining length */
JMF 0:082731ede69f 410 rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen);
JMF 0:082731ede69f 411 if(AWS_SUCCESS != rc) {
JMF 0:082731ede69f 412 FUNC_EXIT_RC(rc);
JMF 0:082731ede69f 413 }
JMF 0:082731ede69f 414 curdata += (readBytesLen);
JMF 0:082731ede69f 415 enddata = curdata + decodedLen;
JMF 0:082731ede69f 416
JMF 0:082731ede69f 417 if(enddata - curdata < 2) {
JMF 0:082731ede69f 418 FUNC_EXIT_RC(FAILURE);
JMF 0:082731ede69f 419 }
JMF 0:082731ede69f 420
JMF 0:082731ede69f 421 *pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curdata);
JMF 0:082731ede69f 422
JMF 0:082731ede69f 423 FUNC_EXIT_RC(AWS_SUCCESS);
JMF 0:082731ede69f 424 }
JMF 0:082731ede69f 425
JMF 0:082731ede69f 426 #ifdef __cplusplus
JMF 0:082731ede69f 427 }
JMF 0:082731ede69f 428 #endif