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_connect.c
peyo 0:cd5404401c2f 35 * @brief MQTT client connect API definition and related functions
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.h>
peyo 0:cd5404401c2f 43 #include "aws_iot_mqtt_client_interface.h"
peyo 0:cd5404401c2f 44 #include "aws_iot_mqtt_client_common_internal.h"
peyo 0:cd5404401c2f 45
peyo 0:cd5404401c2f 46 typedef union {
peyo 0:cd5404401c2f 47 uint8_t all; /**< all connect flags */
peyo 0:cd5404401c2f 48 #if defined(REVERSED)
peyo 0:cd5404401c2f 49 struct
peyo 0:cd5404401c2f 50 {
peyo 0:cd5404401c2f 51 unsigned int username : 1; /**< 3.1 user name */
peyo 0:cd5404401c2f 52 unsigned int password : 1; /**< 3.1 password */
peyo 0:cd5404401c2f 53 unsigned int willRetain : 1; /**< will retain setting */
peyo 0:cd5404401c2f 54 unsigned int willQoS : 2; /**< will QoS value */
peyo 0:cd5404401c2f 55 unsigned int will : 1; /**< will flag */
peyo 0:cd5404401c2f 56 unsigned int cleansession : 1; /**< clean session flag */
peyo 0:cd5404401c2f 57 unsigned int : 1; /**< unused */
peyo 0:cd5404401c2f 58 } bits;
peyo 0:cd5404401c2f 59 #else
peyo 0:cd5404401c2f 60 struct {
peyo 0:cd5404401c2f 61 unsigned int : 1;
peyo 0:cd5404401c2f 62 /**< unused */
peyo 0:cd5404401c2f 63 unsigned int cleansession : 1;
peyo 0:cd5404401c2f 64 /**< cleansession flag */
peyo 0:cd5404401c2f 65 unsigned int will : 1;
peyo 0:cd5404401c2f 66 /**< will flag */
peyo 0:cd5404401c2f 67 unsigned int willQoS : 2;
peyo 0:cd5404401c2f 68 /**< will QoS value */
peyo 0:cd5404401c2f 69 unsigned int willRetain : 1;
peyo 0:cd5404401c2f 70 /**< will retain setting */
peyo 0:cd5404401c2f 71 unsigned int password : 1;
peyo 0:cd5404401c2f 72 /**< 3.1 password */
peyo 0:cd5404401c2f 73 unsigned int username : 1; /**< 3.1 user name */
peyo 0:cd5404401c2f 74 } bits;
peyo 0:cd5404401c2f 75 #endif
peyo 0:cd5404401c2f 76 } MQTT_Connect_Header_Flags;
peyo 0:cd5404401c2f 77 /**< connect flags byte */
peyo 0:cd5404401c2f 78
peyo 0:cd5404401c2f 79 typedef union {
peyo 0:cd5404401c2f 80 uint8_t all; /**< all connack flags */
peyo 0:cd5404401c2f 81 #if defined(REVERSED)
peyo 0:cd5404401c2f 82 struct
peyo 0:cd5404401c2f 83 {
peyo 0:cd5404401c2f 84 unsigned int sessionpresent : 1; /**< session present flag */
peyo 0:cd5404401c2f 85 unsigned int : 7; /**< unused */
peyo 0:cd5404401c2f 86 } bits;
peyo 0:cd5404401c2f 87 #else
peyo 0:cd5404401c2f 88 struct {
peyo 0:cd5404401c2f 89 unsigned int : 7;
peyo 0:cd5404401c2f 90 /**< unused */
peyo 0:cd5404401c2f 91 unsigned int sessionpresent : 1; /**< session present flag */
peyo 0:cd5404401c2f 92 } bits;
peyo 0:cd5404401c2f 93 #endif
peyo 0:cd5404401c2f 94 } MQTT_Connack_Header_Flags;
peyo 0:cd5404401c2f 95 /**< connack flags byte */
peyo 0:cd5404401c2f 96
peyo 0:cd5404401c2f 97 typedef enum {
peyo 0:cd5404401c2f 98 CONNACK_CONNECTION_ACCEPTED = 0,
peyo 0:cd5404401c2f 99 CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1,
peyo 0:cd5404401c2f 100 CONNACK_IDENTIFIER_REJECTED_ERROR = 2,
peyo 0:cd5404401c2f 101 CONNACK_SERVER_UNAVAILABLE_ERROR = 3,
peyo 0:cd5404401c2f 102 CONNACK_BAD_USERDATA_ERROR = 4,
peyo 0:cd5404401c2f 103 CONNACK_NOT_AUTHORIZED_ERROR = 5
peyo 0:cd5404401c2f 104 } MQTT_Connack_Return_Codes; /**< Connect request response codes from server */
peyo 0:cd5404401c2f 105
peyo 0:cd5404401c2f 106
peyo 0:cd5404401c2f 107 /**
peyo 0:cd5404401c2f 108 * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
peyo 0:cd5404401c2f 109 * @param options the options to be used to build the connect packet
peyo 0:cd5404401c2f 110 * @param the length of buffer needed to contain the serialized version of the packet
peyo 0:cd5404401c2f 111 * @return IoT_Error_t indicating function execution status
peyo 0:cd5404401c2f 112 */
peyo 0:cd5404401c2f 113 static uint32_t _aws_iot_get_connect_packet_length(IoT_Client_Connect_Params *pConnectParams) {
peyo 0:cd5404401c2f 114 uint32_t len;
peyo 0:cd5404401c2f 115 /* Enable when adding further MQTT versions */
peyo 0:cd5404401c2f 116 /*size_t len = 0;
peyo 0:cd5404401c2f 117 switch(pConnectParams->MQTTVersion) {
peyo 0:cd5404401c2f 118 case MQTT_3_1_1:
peyo 0:cd5404401c2f 119 len = 10;
peyo 0:cd5404401c2f 120 break;
peyo 0:cd5404401c2f 121 }*/
peyo 0:cd5404401c2f 122 FUNC_ENTRY;
peyo 0:cd5404401c2f 123
peyo 0:cd5404401c2f 124 len = 10; // Len = 10 for MQTT_3_1_1
peyo 0:cd5404401c2f 125 len = len + pConnectParams->clientIDLen + 2;
peyo 0:cd5404401c2f 126
peyo 0:cd5404401c2f 127 if(pConnectParams->isWillMsgPresent) {
peyo 0:cd5404401c2f 128 len = len + pConnectParams->will.topicNameLen + 2 + pConnectParams->will.msgLen + 2;
peyo 0:cd5404401c2f 129 }
peyo 0:cd5404401c2f 130
peyo 0:cd5404401c2f 131 if(NULL != pConnectParams->pUsername) {
peyo 0:cd5404401c2f 132 len = len + pConnectParams->usernameLen + 2;
peyo 0:cd5404401c2f 133 }
peyo 0:cd5404401c2f 134
peyo 0:cd5404401c2f 135 if(NULL != pConnectParams->pPassword) {
peyo 0:cd5404401c2f 136 len = len + pConnectParams->passwordLen + 2;
peyo 0:cd5404401c2f 137 }
peyo 0:cd5404401c2f 138
peyo 0:cd5404401c2f 139 FUNC_EXIT_RC(len);
peyo 0:cd5404401c2f 140 }
peyo 0:cd5404401c2f 141
peyo 0:cd5404401c2f 142 /**
peyo 0:cd5404401c2f 143 * Serializes the connect options into the buffer.
peyo 0:cd5404401c2f 144 * @param buf the buffer into which the packet will be serialized
peyo 0:cd5404401c2f 145 * @param len the length in bytes of the supplied buffer
peyo 0:cd5404401c2f 146 * @param options the options to be used to build the connect packet
peyo 0:cd5404401c2f 147 * @param serialized length
peyo 0:cd5404401c2f 148 * @return IoT_Error_t indicating function execution status
peyo 0:cd5404401c2f 149 */
peyo 0:cd5404401c2f 150 static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t txBufLen,
peyo 0:cd5404401c2f 151 IoT_Client_Connect_Params *pConnectParams,
peyo 0:cd5404401c2f 152 size_t *pSerializedLen) {
peyo 0:cd5404401c2f 153 unsigned char *ptr;
peyo 0:cd5404401c2f 154 uint32_t len;
peyo 0:cd5404401c2f 155 IoT_Error_t rc;
peyo 0:cd5404401c2f 156 MQTTHeader header = {0};
peyo 0:cd5404401c2f 157 MQTT_Connect_Header_Flags flags = {0};
peyo 0:cd5404401c2f 158
peyo 0:cd5404401c2f 159 FUNC_ENTRY;
peyo 0:cd5404401c2f 160
peyo 0:cd5404401c2f 161 if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen ||
peyo 0:cd5404401c2f 162 (NULL == pConnectParams->pClientID && 0 != pConnectParams->clientIDLen) ||
peyo 0:cd5404401c2f 163 (NULL != pConnectParams->pClientID && 0 == pConnectParams->clientIDLen)) {
peyo 0:cd5404401c2f 164 FUNC_EXIT_RC(NULL_VALUE_ERROR);
peyo 0:cd5404401c2f 165 }
peyo 0:cd5404401c2f 166
peyo 0:cd5404401c2f 167 /* Check needed here before we start writing to the Tx buffer */
peyo 0:cd5404401c2f 168 switch(pConnectParams->MQTTVersion) {
peyo 0:cd5404401c2f 169 case MQTT_3_1_1:
peyo 0:cd5404401c2f 170 break;
peyo 0:cd5404401c2f 171 default:
peyo 0:cd5404401c2f 172 return MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
peyo 0:cd5404401c2f 173 }
peyo 0:cd5404401c2f 174
peyo 0:cd5404401c2f 175 ptr = pTxBuf;
peyo 0:cd5404401c2f 176 len = _aws_iot_get_connect_packet_length(pConnectParams);
peyo 0:cd5404401c2f 177 if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(len) > txBufLen) {
peyo 0:cd5404401c2f 178 FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR);
peyo 0:cd5404401c2f 179 }
peyo 0:cd5404401c2f 180
peyo 0:cd5404401c2f 181 rc = aws_iot_mqtt_internal_init_header(&header, CONNECT, QOS0, 0, 0);
peyo 0:cd5404401c2f 182 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 183 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 184 }
peyo 0:cd5404401c2f 185
peyo 0:cd5404401c2f 186 aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */
peyo 0:cd5404401c2f 187
peyo 0:cd5404401c2f 188 ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, len); /* write remaining length */
peyo 0:cd5404401c2f 189
peyo 0:cd5404401c2f 190 // Enable if adding support for more versions
peyo 0:cd5404401c2f 191 //if(MQTT_3_1_1 == pConnectParams->MQTTVersion) {
peyo 0:cd5404401c2f 192 aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4);
peyo 0:cd5404401c2f 193 aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pConnectParams->MQTTVersion);
peyo 0:cd5404401c2f 194 //}
peyo 0:cd5404401c2f 195
peyo 0:cd5404401c2f 196 flags.all = 0;
peyo 0:cd5404401c2f 197 flags.bits.cleansession = (pConnectParams->isCleanSession) ? 1 : 0;
peyo 0:cd5404401c2f 198 flags.bits.will = (pConnectParams->isWillMsgPresent) ? 1 : 0;
peyo 0:cd5404401c2f 199 if(flags.bits.will) {
peyo 0:cd5404401c2f 200 flags.bits.willQoS = pConnectParams->will.qos;
peyo 0:cd5404401c2f 201 flags.bits.willRetain = (pConnectParams->will.isRetained) ? 1 : 0;
peyo 0:cd5404401c2f 202 }
peyo 0:cd5404401c2f 203
peyo 0:cd5404401c2f 204 if(pConnectParams->pUsername) {
peyo 0:cd5404401c2f 205 flags.bits.username = 1;
peyo 0:cd5404401c2f 206 }
peyo 0:cd5404401c2f 207
peyo 0:cd5404401c2f 208 if(pConnectParams->pPassword) {
peyo 0:cd5404401c2f 209 flags.bits.password = 1;
peyo 0:cd5404401c2f 210 }
peyo 0:cd5404401c2f 211
peyo 0:cd5404401c2f 212 aws_iot_mqtt_internal_write_char(&ptr, flags.all);
peyo 0:cd5404401c2f 213 aws_iot_mqtt_internal_write_uint_16(&ptr, pConnectParams->keepAliveIntervalInSec);
peyo 0:cd5404401c2f 214
peyo 0:cd5404401c2f 215 /* If the code have passed the check for incorrect values above, no client id was passed as argument */
peyo 0:cd5404401c2f 216 if(NULL == pConnectParams->pClientID) {
peyo 0:cd5404401c2f 217 aws_iot_mqtt_internal_write_uint_16(&ptr, 0);
peyo 0:cd5404401c2f 218 } else {
peyo 0:cd5404401c2f 219 aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen);
peyo 0:cd5404401c2f 220 }
peyo 0:cd5404401c2f 221
peyo 0:cd5404401c2f 222 if(pConnectParams->isWillMsgPresent) {
peyo 0:cd5404401c2f 223 aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName,
peyo 0:cd5404401c2f 224 pConnectParams->will.topicNameLen);
peyo 0:cd5404401c2f 225 aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen);
peyo 0:cd5404401c2f 226 }
peyo 0:cd5404401c2f 227
peyo 0:cd5404401c2f 228 if(flags.bits.username) {
peyo 0:cd5404401c2f 229 aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pUsername, pConnectParams->usernameLen);
peyo 0:cd5404401c2f 230 }
peyo 0:cd5404401c2f 231
peyo 0:cd5404401c2f 232 if(flags.bits.password) {
peyo 0:cd5404401c2f 233 aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen);
peyo 0:cd5404401c2f 234 }
peyo 0:cd5404401c2f 235
peyo 0:cd5404401c2f 236 *pSerializedLen = (size_t) (ptr - pTxBuf);
peyo 0:cd5404401c2f 237
peyo 0:cd5404401c2f 238 FUNC_EXIT_RC(SUCCESS);
peyo 0:cd5404401c2f 239 }
peyo 0:cd5404401c2f 240
peyo 0:cd5404401c2f 241 /**
peyo 0:cd5404401c2f 242 * Deserializes the supplied (wire) buffer into connack data - return code
peyo 0:cd5404401c2f 243 * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
peyo 0:cd5404401c2f 244 * @param connack_rc returned integer value of the connack return code
peyo 0:cd5404401c2f 245 * @param buf the raw buffer data, of the correct length determined by the remaining length field
peyo 0:cd5404401c2f 246 * @param buflen the length in bytes of the data in the supplied buffer
peyo 0:cd5404401c2f 247 * @return IoT_Error_t indicating function execution status
peyo 0:cd5404401c2f 248 */
peyo 0:cd5404401c2f 249 static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPresent, IoT_Error_t *pConnackRc,
peyo 0:cd5404401c2f 250 unsigned char *pRxBuf, size_t rxBufLen) {
peyo 0:cd5404401c2f 251 unsigned char *curdata, *enddata;
peyo 0:cd5404401c2f 252 unsigned char connack_rc_char;
peyo 0:cd5404401c2f 253 uint32_t decodedLen, readBytesLen;
peyo 0:cd5404401c2f 254 IoT_Error_t rc;
peyo 0:cd5404401c2f 255 MQTT_Connack_Header_Flags flags = {0};
peyo 0:cd5404401c2f 256 MQTTHeader header = {0};
peyo 0:cd5404401c2f 257
peyo 0:cd5404401c2f 258 FUNC_ENTRY;
peyo 0:cd5404401c2f 259
peyo 0:cd5404401c2f 260 if(NULL == pSessionPresent || NULL == pConnackRc || NULL == pRxBuf) {
peyo 0:cd5404401c2f 261 FUNC_EXIT_RC(NULL_VALUE_ERROR);
peyo 0:cd5404401c2f 262 }
peyo 0:cd5404401c2f 263
peyo 0:cd5404401c2f 264 /* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable,
peyo 0:cd5404401c2f 265 * using that as minimum size
peyo 0:cd5404401c2f 266 * MQTT v3.1.1 Specification 3.2.1 */
peyo 0:cd5404401c2f 267 if(4 > rxBufLen) {
peyo 0:cd5404401c2f 268 FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
peyo 0:cd5404401c2f 269 }
peyo 0:cd5404401c2f 270
peyo 0:cd5404401c2f 271 curdata = pRxBuf;
peyo 0:cd5404401c2f 272 enddata = NULL;
peyo 0:cd5404401c2f 273 decodedLen = 0;
peyo 0:cd5404401c2f 274 readBytesLen = 0;
peyo 0:cd5404401c2f 275
peyo 0:cd5404401c2f 276 header.byte = aws_iot_mqtt_internal_read_char(&curdata);
peyo 0:cd5404401c2f 277 if(CONNACK != header.bits.type) {
peyo 0:cd5404401c2f 278 FUNC_EXIT_RC(FAILURE);
peyo 0:cd5404401c2f 279 }
peyo 0:cd5404401c2f 280
peyo 0:cd5404401c2f 281 /* read remaining length */
peyo 0:cd5404401c2f 282 rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen);
peyo 0:cd5404401c2f 283 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 284 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 285 }
peyo 0:cd5404401c2f 286
peyo 0:cd5404401c2f 287 /* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */
peyo 0:cd5404401c2f 288 curdata += (readBytesLen);
peyo 0:cd5404401c2f 289 enddata = curdata + decodedLen;
peyo 0:cd5404401c2f 290 if(2 != (enddata - curdata)) {
peyo 0:cd5404401c2f 291 FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR);
peyo 0:cd5404401c2f 292 }
peyo 0:cd5404401c2f 293
peyo 0:cd5404401c2f 294 flags.all = aws_iot_mqtt_internal_read_char(&curdata);
peyo 0:cd5404401c2f 295 *pSessionPresent = flags.bits.sessionpresent;
peyo 0:cd5404401c2f 296 connack_rc_char = aws_iot_mqtt_internal_read_char(&curdata);
peyo 0:cd5404401c2f 297 switch(connack_rc_char) {
peyo 0:cd5404401c2f 298 case CONNACK_CONNECTION_ACCEPTED:
peyo 0:cd5404401c2f 299 *pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED;
peyo 0:cd5404401c2f 300 break;
peyo 0:cd5404401c2f 301 case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
peyo 0:cd5404401c2f 302 *pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
peyo 0:cd5404401c2f 303 break;
peyo 0:cd5404401c2f 304 case CONNACK_IDENTIFIER_REJECTED_ERROR:
peyo 0:cd5404401c2f 305 *pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR;
peyo 0:cd5404401c2f 306 break;
peyo 0:cd5404401c2f 307 case CONNACK_SERVER_UNAVAILABLE_ERROR:
peyo 0:cd5404401c2f 308 *pConnackRc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR;
peyo 0:cd5404401c2f 309 break;
peyo 0:cd5404401c2f 310 case CONNACK_BAD_USERDATA_ERROR:
peyo 0:cd5404401c2f 311 *pConnackRc = MQTT_CONNACK_BAD_USERDATA_ERROR;
peyo 0:cd5404401c2f 312 break;
peyo 0:cd5404401c2f 313 case CONNACK_NOT_AUTHORIZED_ERROR:
peyo 0:cd5404401c2f 314 *pConnackRc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR;
peyo 0:cd5404401c2f 315 break;
peyo 0:cd5404401c2f 316 default:
peyo 0:cd5404401c2f 317 *pConnackRc = MQTT_CONNACK_UNKNOWN_ERROR;
peyo 0:cd5404401c2f 318 break;
peyo 0:cd5404401c2f 319 }
peyo 0:cd5404401c2f 320
peyo 0:cd5404401c2f 321 FUNC_EXIT_RC(SUCCESS);
peyo 0:cd5404401c2f 322 }
peyo 0:cd5404401c2f 323
peyo 0:cd5404401c2f 324 /**
peyo 0:cd5404401c2f 325 * @brief Check if client state is valid for a connect request
peyo 0:cd5404401c2f 326 *
peyo 0:cd5404401c2f 327 * Called to check if client state is valid for a connect request
peyo 0:cd5404401c2f 328 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 329 *
peyo 0:cd5404401c2f 330 * @return bool true = state is valid, false = not valid
peyo 0:cd5404401c2f 331 */
peyo 0:cd5404401c2f 332 static bool _aws_iot_mqtt_is_client_state_valid_for_connect(ClientState clientState) {
peyo 0:cd5404401c2f 333 bool isValid = false;
peyo 0:cd5404401c2f 334
peyo 0:cd5404401c2f 335 switch(clientState) {
peyo 0:cd5404401c2f 336 case CLIENT_STATE_INVALID:
peyo 0:cd5404401c2f 337 isValid = false;
peyo 0:cd5404401c2f 338 break;
peyo 0:cd5404401c2f 339 case CLIENT_STATE_INITIALIZED:
peyo 0:cd5404401c2f 340 isValid = true;
peyo 0:cd5404401c2f 341 break;
peyo 0:cd5404401c2f 342 case CLIENT_STATE_CONNECTING:
peyo 0:cd5404401c2f 343 case CLIENT_STATE_CONNECTED_IDLE:
peyo 0:cd5404401c2f 344 case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS:
peyo 0:cd5404401c2f 345 case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS:
peyo 0:cd5404401c2f 346 case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS:
peyo 0:cd5404401c2f 347 case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS:
peyo 0:cd5404401c2f 348 case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS:
peyo 0:cd5404401c2f 349 case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN:
peyo 0:cd5404401c2f 350 case CLIENT_STATE_DISCONNECTING:
peyo 0:cd5404401c2f 351 isValid = false;
peyo 0:cd5404401c2f 352 break;
peyo 0:cd5404401c2f 353 case CLIENT_STATE_DISCONNECTED_ERROR:
peyo 0:cd5404401c2f 354 case CLIENT_STATE_DISCONNECTED_MANUALLY:
peyo 0:cd5404401c2f 355 case CLIENT_STATE_PENDING_RECONNECT:
peyo 0:cd5404401c2f 356 isValid = true;
peyo 0:cd5404401c2f 357 break;
peyo 0:cd5404401c2f 358 default:
peyo 0:cd5404401c2f 359 break;
peyo 0:cd5404401c2f 360 }
peyo 0:cd5404401c2f 361
peyo 0:cd5404401c2f 362 return isValid;
peyo 0:cd5404401c2f 363 }
peyo 0:cd5404401c2f 364
peyo 0:cd5404401c2f 365 /**
peyo 0:cd5404401c2f 366 * @brief MQTT Connection Function
peyo 0:cd5404401c2f 367 *
peyo 0:cd5404401c2f 368 * Called to establish an MQTT connection with the AWS IoT Service
peyo 0:cd5404401c2f 369 * This is the internal function which is called by the connect API to perform the operation.
peyo 0:cd5404401c2f 370 * Not meant to be called directly as it doesn't do validations or client state changes
peyo 0:cd5404401c2f 371 *
peyo 0:cd5404401c2f 372 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 373 * @param pConnectParams Pointer to MQTT connection parameters
peyo 0:cd5404401c2f 374 *
peyo 0:cd5404401c2f 375 * @return An IoT Error Type defining successful/failed connection
peyo 0:cd5404401c2f 376 */
peyo 0:cd5404401c2f 377 static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) {
peyo 0:cd5404401c2f 378 TimerAWS connect_timer;
peyo 0:cd5404401c2f 379 IoT_Error_t connack_rc = FAILURE;
peyo 0:cd5404401c2f 380 char sessionPresent = 0;
peyo 0:cd5404401c2f 381 size_t len = 0;
peyo 0:cd5404401c2f 382 IoT_Error_t rc = FAILURE;
peyo 0:cd5404401c2f 383
peyo 0:cd5404401c2f 384 FUNC_ENTRY;
peyo 0:cd5404401c2f 385
peyo 0:cd5404401c2f 386 if(NULL != pConnectParams) {
peyo 0:cd5404401c2f 387 /* override default options if new options were supplied */
peyo 0:cd5404401c2f 388 rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams);
peyo 0:cd5404401c2f 389 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 390 FUNC_EXIT_RC(MQTT_CONNECTION_ERROR);
peyo 0:cd5404401c2f 391 }
peyo 0:cd5404401c2f 392 }
peyo 0:cd5404401c2f 393
peyo 0:cd5404401c2f 394 rc = pClient->networkStack.connect(&(pClient->networkStack), NULL);
peyo 0:cd5404401c2f 395 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 396 /* TLS Connect failed, return error */
peyo 0:cd5404401c2f 397 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 398 }
peyo 0:cd5404401c2f 399
peyo 0:cd5404401c2f 400 init_timer(&connect_timer);
peyo 0:cd5404401c2f 401 countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs);
peyo 0:cd5404401c2f 402
peyo 0:cd5404401c2f 403 pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec;
peyo 0:cd5404401c2f 404 rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
peyo 0:cd5404401c2f 405 &(pClient->clientData.options), &len);
peyo 0:cd5404401c2f 406 if(SUCCESS != rc || 0 >= len) {
peyo 0:cd5404401c2f 407 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 408 }
peyo 0:cd5404401c2f 409
peyo 0:cd5404401c2f 410 /* send the connect packet */
peyo 0:cd5404401c2f 411 rc = aws_iot_mqtt_internal_send_packet(pClient, len, &connect_timer);
peyo 0:cd5404401c2f 412 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 413 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 414 }
peyo 0:cd5404401c2f 415
peyo 0:cd5404401c2f 416 /* this will be a blocking call, wait for the CONNACK */
peyo 0:cd5404401c2f 417 rc = aws_iot_mqtt_internal_wait_for_read(pClient, CONNACK, &connect_timer);
peyo 0:cd5404401c2f 418 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 419 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 420 }
peyo 0:cd5404401c2f 421
peyo 0:cd5404401c2f 422 /* Received CONNACK, check the return code */
peyo 0:cd5404401c2f 423 rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf,
peyo 0:cd5404401c2f 424 pClient->clientData.readBufSize);
peyo 0:cd5404401c2f 425 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 426 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 427 }
peyo 0:cd5404401c2f 428
peyo 0:cd5404401c2f 429 if(MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) {
peyo 0:cd5404401c2f 430 FUNC_EXIT_RC(connack_rc);
peyo 0:cd5404401c2f 431 }
peyo 0:cd5404401c2f 432
peyo 0:cd5404401c2f 433 pClient->clientStatus.isPingOutstanding = false;
peyo 0:cd5404401c2f 434 countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval);
peyo 0:cd5404401c2f 435
peyo 0:cd5404401c2f 436 FUNC_EXIT_RC(SUCCESS);
peyo 0:cd5404401c2f 437 }
peyo 0:cd5404401c2f 438
peyo 0:cd5404401c2f 439 /**
peyo 0:cd5404401c2f 440 * @brief MQTT Connection Function
peyo 0:cd5404401c2f 441 *
peyo 0:cd5404401c2f 442 * Called to establish an MQTT connection with the AWS IoT Service
peyo 0:cd5404401c2f 443 * This is the outer function which does the validations and calls the internal connect above
peyo 0:cd5404401c2f 444 * to perform the actual operation. It is also responsible for client state changes
peyo 0:cd5404401c2f 445 *
peyo 0:cd5404401c2f 446 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 447 * @param pConnectParams Pointer to MQTT connection parameters
peyo 0:cd5404401c2f 448 *
peyo 0:cd5404401c2f 449 * @return An IoT Error Type defining successful/failed connection
peyo 0:cd5404401c2f 450 */
peyo 0:cd5404401c2f 451 IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) {
peyo 0:cd5404401c2f 452 IoT_Error_t rc, disconRc;
peyo 0:cd5404401c2f 453 ClientState clientState;
peyo 0:cd5404401c2f 454
peyo 0:cd5404401c2f 455 FUNC_ENTRY;
peyo 0:cd5404401c2f 456
peyo 0:cd5404401c2f 457 if(NULL == pClient) {
peyo 0:cd5404401c2f 458 FUNC_EXIT_RC(NULL_VALUE_ERROR);
peyo 0:cd5404401c2f 459 }
peyo 0:cd5404401c2f 460
peyo 0:cd5404401c2f 461 clientState = aws_iot_mqtt_get_client_state(pClient);
peyo 0:cd5404401c2f 462
peyo 0:cd5404401c2f 463 if(false == _aws_iot_mqtt_is_client_state_valid_for_connect(clientState)) {
peyo 0:cd5404401c2f 464 /* Don't send connect packet again if we are already connected
peyo 0:cd5404401c2f 465 * or in the process of connecting/disconnecting */
peyo 0:cd5404401c2f 466 FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR);
peyo 0:cd5404401c2f 467 }
peyo 0:cd5404401c2f 468
peyo 0:cd5404401c2f 469 aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTING);
peyo 0:cd5404401c2f 470
peyo 0:cd5404401c2f 471 rc = _aws_iot_mqtt_internal_connect(pClient, pConnectParams);
peyo 0:cd5404401c2f 472
peyo 0:cd5404401c2f 473 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 474 pClient->networkStack.disconnect(&(pClient->networkStack));
peyo 0:cd5404401c2f 475 disconRc = pClient->networkStack.destroy(&(pClient->networkStack));
peyo 0:cd5404401c2f 476 aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_DISCONNECTED_ERROR);
peyo 0:cd5404401c2f 477 } else {
peyo 0:cd5404401c2f 478 aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED_IDLE);
peyo 0:cd5404401c2f 479 }
peyo 0:cd5404401c2f 480
peyo 0:cd5404401c2f 481 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 482 }
peyo 0:cd5404401c2f 483
peyo 0:cd5404401c2f 484 /**
peyo 0:cd5404401c2f 485 * @brief Disconnect an MQTT Connection
peyo 0:cd5404401c2f 486 *
peyo 0:cd5404401c2f 487 * Called to send a disconnect message to the broker.
peyo 0:cd5404401c2f 488 * This is the internal function which is called by the disconnect API to perform the operation.
peyo 0:cd5404401c2f 489 * Not meant to be called directly as it doesn't do validations or client state changes
peyo 0:cd5404401c2f 490 *
peyo 0:cd5404401c2f 491 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 492 *
peyo 0:cd5404401c2f 493 * @return An IoT Error Type defining successful/failed send of the disconnect control packet.
peyo 0:cd5404401c2f 494 */
peyo 0:cd5404401c2f 495 IoT_Error_t _aws_iot_mqtt_internal_disconnect(AWS_IoT_Client *pClient) {
peyo 0:cd5404401c2f 496 /* We might wait for incomplete incoming publishes to complete */
peyo 0:cd5404401c2f 497 TimerAWS timer;
peyo 0:cd5404401c2f 498 size_t serialized_len = 0;
peyo 0:cd5404401c2f 499 IoT_Error_t rc;
peyo 0:cd5404401c2f 500
peyo 0:cd5404401c2f 501 FUNC_ENTRY;
peyo 0:cd5404401c2f 502
peyo 0:cd5404401c2f 503 rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
peyo 0:cd5404401c2f 504 DISCONNECT,
peyo 0:cd5404401c2f 505 &serialized_len);
peyo 0:cd5404401c2f 506 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 507 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 508 }
peyo 0:cd5404401c2f 509
peyo 0:cd5404401c2f 510 init_timer(&timer);
peyo 0:cd5404401c2f 511 countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
peyo 0:cd5404401c2f 512
peyo 0:cd5404401c2f 513 /* send the disconnect packet */
peyo 0:cd5404401c2f 514 if(serialized_len > 0) {
peyo 0:cd5404401c2f 515 rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer);
peyo 0:cd5404401c2f 516 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 517 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 518 }
peyo 0:cd5404401c2f 519 }
peyo 0:cd5404401c2f 520
peyo 0:cd5404401c2f 521 /* Clean network stack */
peyo 0:cd5404401c2f 522 pClient->networkStack.disconnect(&(pClient->networkStack));
peyo 0:cd5404401c2f 523 rc = pClient->networkStack.destroy(&(pClient->networkStack));
peyo 0:cd5404401c2f 524 if(0 != rc) {
peyo 0:cd5404401c2f 525 /* TLS Destroy failed, return error */
peyo 0:cd5404401c2f 526 FUNC_EXIT_RC(FAILURE);
peyo 0:cd5404401c2f 527 }
peyo 0:cd5404401c2f 528
peyo 0:cd5404401c2f 529 FUNC_EXIT_RC(SUCCESS);
peyo 0:cd5404401c2f 530 }
peyo 0:cd5404401c2f 531
peyo 0:cd5404401c2f 532 /**
peyo 0:cd5404401c2f 533 * @brief Disconnect an MQTT Connection
peyo 0:cd5404401c2f 534 *
peyo 0:cd5404401c2f 535 * Called to send a disconnect message to the broker.
peyo 0:cd5404401c2f 536 * This is the outer function which does the validations and calls the internal disconnect above
peyo 0:cd5404401c2f 537 * to perform the actual operation. It is also responsible for client state changes
peyo 0:cd5404401c2f 538 *
peyo 0:cd5404401c2f 539 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 540 *
peyo 0:cd5404401c2f 541 * @return An IoT Error Type defining successful/failed send of the disconnect control packet.
peyo 0:cd5404401c2f 542 */
peyo 0:cd5404401c2f 543 IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient) {
peyo 0:cd5404401c2f 544 ClientState clientState;
peyo 0:cd5404401c2f 545 IoT_Error_t rc;
peyo 0:cd5404401c2f 546
peyo 0:cd5404401c2f 547 FUNC_ENTRY;
peyo 0:cd5404401c2f 548
peyo 0:cd5404401c2f 549 if(NULL == pClient) {
peyo 0:cd5404401c2f 550 FUNC_EXIT_RC(NULL_VALUE_ERROR);
peyo 0:cd5404401c2f 551 }
peyo 0:cd5404401c2f 552
peyo 0:cd5404401c2f 553 clientState = aws_iot_mqtt_get_client_state(pClient);
peyo 0:cd5404401c2f 554 if(!aws_iot_mqtt_is_client_connected(pClient)) {
peyo 0:cd5404401c2f 555 /* Network is already disconnected. Do nothing */
peyo 0:cd5404401c2f 556 FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR);
peyo 0:cd5404401c2f 557 }
peyo 0:cd5404401c2f 558
peyo 0:cd5404401c2f 559 rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_DISCONNECTING);
peyo 0:cd5404401c2f 560 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 561 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 562 }
peyo 0:cd5404401c2f 563
peyo 0:cd5404401c2f 564 rc = _aws_iot_mqtt_internal_disconnect(pClient);
peyo 0:cd5404401c2f 565
peyo 0:cd5404401c2f 566 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 567 pClient->clientStatus.clientState = clientState;
peyo 0:cd5404401c2f 568 } else {
peyo 0:cd5404401c2f 569 /* If called from Keepalive, this gets set to CLIENT_STATE_DISCONNECTED_ERROR */
peyo 0:cd5404401c2f 570 pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_MANUALLY;
peyo 0:cd5404401c2f 571 }
peyo 0:cd5404401c2f 572
peyo 0:cd5404401c2f 573 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 574 }
peyo 0:cd5404401c2f 575
peyo 0:cd5404401c2f 576 /**
peyo 0:cd5404401c2f 577 * @brief MQTT Manual Re-Connection Function
peyo 0:cd5404401c2f 578 *
peyo 0:cd5404401c2f 579 * Called to establish an MQTT connection with the AWS IoT Service
peyo 0:cd5404401c2f 580 * using parameters from the last time a connection was attempted
peyo 0:cd5404401c2f 581 * Use after disconnect to start the reconnect process manually
peyo 0:cd5404401c2f 582 * Makes only one reconnect attempt. Sets the client state to
peyo 0:cd5404401c2f 583 * pending reconnect in case of failure
peyo 0:cd5404401c2f 584 *
peyo 0:cd5404401c2f 585 * @param pClient Reference to the IoT Client
peyo 0:cd5404401c2f 586 *
peyo 0:cd5404401c2f 587 * @return An IoT Error Type defining successful/failed connection
peyo 0:cd5404401c2f 588 */
peyo 0:cd5404401c2f 589 IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient) {
peyo 0:cd5404401c2f 590 IoT_Error_t rc;
peyo 0:cd5404401c2f 591
peyo 0:cd5404401c2f 592 FUNC_ENTRY;
peyo 0:cd5404401c2f 593
peyo 0:cd5404401c2f 594 if(NULL == pClient) {
peyo 0:cd5404401c2f 595 FUNC_EXIT_RC(NULL_VALUE_ERROR);
peyo 0:cd5404401c2f 596 }
peyo 0:cd5404401c2f 597
peyo 0:cd5404401c2f 598 if(aws_iot_mqtt_is_client_connected(pClient)) {
peyo 0:cd5404401c2f 599 FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR);
peyo 0:cd5404401c2f 600 }
peyo 0:cd5404401c2f 601
peyo 0:cd5404401c2f 602 /* Ignoring return code. failures expected if network is disconnected */
peyo 0:cd5404401c2f 603 rc = aws_iot_mqtt_connect(pClient, NULL);
peyo 0:cd5404401c2f 604
peyo 0:cd5404401c2f 605 /* If still disconnected handle disconnect */
peyo 0:cd5404401c2f 606 if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) {
peyo 0:cd5404401c2f 607 aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, CLIENT_STATE_PENDING_RECONNECT);
peyo 0:cd5404401c2f 608 FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT);
peyo 0:cd5404401c2f 609 }
peyo 0:cd5404401c2f 610
peyo 0:cd5404401c2f 611 rc = aws_iot_mqtt_resubscribe(pClient);
peyo 0:cd5404401c2f 612 if(SUCCESS != rc) {
peyo 0:cd5404401c2f 613 FUNC_EXIT_RC(rc);
peyo 0:cd5404401c2f 614 }
peyo 0:cd5404401c2f 615
peyo 0:cd5404401c2f 616 FUNC_EXIT_RC(NETWORK_RECONNECTED);
peyo 0:cd5404401c2f 617 }
peyo 0:cd5404401c2f 618
peyo 0:cd5404401c2f 619 #ifdef __cplusplus
peyo 0:cd5404401c2f 620 }
peyo 0:cd5404401c2f 621 #endif