this is fork and i will modify for STM32

Fork of AWS-test by Pierre-Marie Ancèle

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aws_iot_mqtt_client_connect.cpp Source File

aws_iot_mqtt_client_connect.cpp

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_connect.c
00035  * @brief MQTT client connect API definition and related functions
00036  */
00037 
00038 #ifdef __cplusplus
00039 extern "C" {
00040 #endif
00041 
00042 #include <aws_iot_mqtt_client.h>
00043 #include "aws_iot_mqtt_client_interface.h"
00044 #include "aws_iot_mqtt_client_common_internal.h"
00045 
00046 typedef union {
00047     uint8_t all;    /**< all connect flags */
00048 #if defined(REVERSED)
00049     struct
00050     {
00051         unsigned int username : 1;      /**< 3.1 user name */
00052         unsigned int password : 1;      /**< 3.1 password */
00053         unsigned int willRetain : 1;    /**< will retain setting */
00054         unsigned int willQoS : 2;       /**< will QoS value */
00055         unsigned int will : 1;          /**< will flag */
00056         unsigned int cleansession : 1;  /**< clean session flag */
00057         unsigned int : 1;               /**< unused */
00058     } bits;
00059 #else
00060     struct {
00061         unsigned int : 1;
00062         /**< unused */
00063         unsigned int cleansession : 1;
00064         /**< cleansession flag */
00065         unsigned int will : 1;
00066         /**< will flag */
00067         unsigned int willQoS : 2;
00068         /**< will QoS value */
00069         unsigned int willRetain : 1;
00070         /**< will retain setting */
00071         unsigned int password : 1;
00072         /**< 3.1 password */
00073         unsigned int username : 1;        /**< 3.1 user name */
00074     } bits;
00075 #endif
00076 } MQTT_Connect_Header_Flags;
00077 /**< connect flags byte */
00078 
00079 typedef union {
00080     uint8_t all;                            /**< all connack flags */
00081 #if defined(REVERSED)
00082     struct
00083     {
00084         unsigned int sessionpresent : 1;    /**< session present flag */
00085         unsigned int : 7;                   /**< unused */
00086     } bits;
00087 #else
00088     struct {
00089         unsigned int : 7;
00090         /**< unused */
00091         unsigned int sessionpresent : 1;    /**< session present flag */
00092     } bits;
00093 #endif
00094 } MQTT_Connack_Header_Flags;
00095 /**< connack flags byte */
00096 
00097 typedef enum {
00098     CONNACK_CONNECTION_ACCEPTED = 0,
00099     CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = 1,
00100     CONNACK_IDENTIFIER_REJECTED_ERROR = 2,
00101     CONNACK_SERVER_UNAVAILABLE_ERROR = 3,
00102     CONNACK_BAD_USERDATA_ERROR = 4,
00103     CONNACK_NOT_AUTHORIZED_ERROR = 5
00104 } MQTT_Connack_Return_Codes;    /**< Connect request response codes from server */
00105 
00106 
00107 /**
00108   * Determines the length of the MQTT connect packet that would be produced using the supplied connect options.
00109   * @param options the options to be used to build the connect packet
00110   * @param the length of buffer needed to contain the serialized version of the packet
00111   * @return IoT_Error_t indicating function execution status
00112   */
00113 static uint32_t _aws_iot_get_connect_packet_length(IoT_Client_Connect_Params *pConnectParams) {
00114     uint32_t len;
00115     /* Enable when adding further MQTT versions */
00116     /*size_t len = 0;
00117     switch(pConnectParams->MQTTVersion) {
00118         case MQTT_3_1_1:
00119             len = 10;
00120             break;
00121     }*/
00122     FUNC_ENTRY;
00123 
00124     len = 10; // Len = 10 for MQTT_3_1_1
00125     len = len + pConnectParams->clientIDLen + 2;
00126 
00127     if(pConnectParams->isWillMsgPresent) {
00128         len = len + pConnectParams->will.topicNameLen + 2 + pConnectParams->will.msgLen + 2;
00129     }
00130 
00131     if(NULL != pConnectParams->pUsername) {
00132         len = len + pConnectParams->usernameLen + 2;
00133     }
00134 
00135     if(NULL != pConnectParams->pPassword) {
00136         len = len + pConnectParams->passwordLen + 2;
00137     }
00138 
00139     FUNC_EXIT_RC(len);
00140 }
00141 
00142 /**
00143   * Serializes the connect options into the buffer.
00144   * @param buf the buffer into which the packet will be serialized
00145   * @param len the length in bytes of the supplied buffer
00146   * @param options the options to be used to build the connect packet
00147   * @param serialized length
00148   * @return IoT_Error_t indicating function execution status
00149   */
00150 static IoT_Error_t _aws_iot_mqtt_serialize_connect(unsigned char *pTxBuf, size_t txBufLen,
00151                                                    IoT_Client_Connect_Params *pConnectParams,
00152                                                    size_t *pSerializedLen) {
00153     unsigned char *ptr;
00154     uint32_t len;
00155     IoT_Error_t rc;
00156     MQTTHeader header = {0};
00157     MQTT_Connect_Header_Flags flags = {0};
00158 
00159     FUNC_ENTRY;
00160 
00161     if(NULL == pTxBuf || NULL == pConnectParams || NULL == pSerializedLen ||
00162        (NULL == pConnectParams->pClientID && 0 != pConnectParams->clientIDLen) ||
00163        (NULL != pConnectParams->pClientID && 0 == pConnectParams->clientIDLen)) {
00164         FUNC_EXIT_RC(NULL_VALUE_ERROR);
00165     }
00166 
00167     /* Check needed here before we start writing to the Tx buffer */
00168     switch(pConnectParams->MQTTVersion) {
00169         case MQTT_3_1_1:
00170             break;
00171         default:
00172             return MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
00173     }
00174 
00175     ptr = pTxBuf;
00176     len = _aws_iot_get_connect_packet_length(pConnectParams);
00177     if(aws_iot_mqtt_internal_get_final_packet_length_from_remaining_length(len) > txBufLen) {
00178         FUNC_EXIT_RC(MQTT_TX_BUFFER_TOO_SHORT_ERROR);
00179     }
00180 
00181     rc = aws_iot_mqtt_internal_init_header(&header, CONNECT, QOS0, 0, 0);
00182     if(IOT_SUCCESS != rc) {
00183         FUNC_EXIT_RC(rc);
00184     }
00185 
00186     aws_iot_mqtt_internal_write_char(&ptr, header.byte); /* write header */
00187 
00188     ptr += aws_iot_mqtt_internal_write_len_to_buffer(ptr, len); /* write remaining length */
00189 
00190     // Enable if adding support for more versions
00191     //if(MQTT_3_1_1 == pConnectParams->MQTTVersion) {
00192     aws_iot_mqtt_internal_write_utf8_string(&ptr, "MQTT", 4);
00193     aws_iot_mqtt_internal_write_char(&ptr, (unsigned char) pConnectParams->MQTTVersion);
00194     //}
00195 
00196     flags.all = 0;
00197     flags.bits.cleansession = (pConnectParams->isCleanSession) ? 1 : 0;
00198     flags.bits.will = (pConnectParams->isWillMsgPresent) ? 1 : 0;
00199     if(flags.bits.will) {
00200         flags.bits.willQoS = pConnectParams->will.qos;
00201         flags.bits.willRetain = (pConnectParams->will.isRetained) ? 1 : 0;
00202     }
00203 
00204     if(pConnectParams->pUsername) {
00205         flags.bits.username = 1;
00206     }
00207 
00208     if(pConnectParams->pPassword) {
00209         flags.bits.password = 1;
00210     }
00211 
00212     aws_iot_mqtt_internal_write_char(&ptr, flags.all);
00213     aws_iot_mqtt_internal_write_uint_16(&ptr, pConnectParams->keepAliveIntervalInSec);
00214 
00215     /* If the code have passed the check for incorrect values above, no client id was passed as argument */
00216     if(NULL == pConnectParams->pClientID) {
00217         aws_iot_mqtt_internal_write_uint_16(&ptr, 0);
00218     } else {
00219         aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pClientID, pConnectParams->clientIDLen);
00220     }
00221 
00222     if(pConnectParams->isWillMsgPresent) {
00223         aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pTopicName,
00224                                                 pConnectParams->will.topicNameLen);
00225         aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->will.pMessage, pConnectParams->will.msgLen);
00226     }
00227 
00228     if(flags.bits.username) {
00229         aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pUsername, pConnectParams->usernameLen);
00230     }
00231 
00232     if(flags.bits.password) {
00233         aws_iot_mqtt_internal_write_utf8_string(&ptr, pConnectParams->pPassword, pConnectParams->passwordLen);
00234     }
00235 
00236     *pSerializedLen = (size_t) (ptr - pTxBuf);
00237 
00238     FUNC_EXIT_RC(IOT_SUCCESS);
00239 }
00240 
00241 /**
00242   * Deserializes the supplied (wire) buffer into connack data - return code
00243   * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
00244   * @param connack_rc returned integer value of the connack return code
00245   * @param buf the raw buffer data, of the correct length determined by the remaining length field
00246   * @param buflen the length in bytes of the data in the supplied buffer
00247   * @return IoT_Error_t indicating function execution status
00248   */
00249 static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPresent, IoT_Error_t *pConnackRc,
00250                                                      unsigned char *pRxBuf, size_t rxBufLen) {
00251     unsigned char *curdata, *enddata;
00252     unsigned char connack_rc_char;
00253     uint32_t decodedLen, readBytesLen;
00254     IoT_Error_t rc;
00255     MQTT_Connack_Header_Flags flags = {0};
00256     MQTTHeader header = {0};
00257 
00258     FUNC_ENTRY;
00259 
00260     if(NULL == pSessionPresent || NULL == pConnackRc || NULL == pRxBuf) {
00261         FUNC_EXIT_RC(NULL_VALUE_ERROR);
00262     }
00263 
00264     /* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable,
00265      * using that as minimum size
00266      * MQTT v3.1.1 Specification 3.2.1 */
00267     if(4 > rxBufLen) {
00268         FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
00269     }
00270 
00271     curdata = pRxBuf;
00272     enddata = NULL;
00273     decodedLen = 0;
00274     readBytesLen = 0;
00275 
00276     header.byte = aws_iot_mqtt_internal_read_char(&curdata);
00277     if(CONNACK != header.bits.type) {
00278         FUNC_EXIT_RC(IOT_FAILURE);
00279     }
00280 
00281     /* read remaining length */
00282     rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen);
00283     if(IOT_SUCCESS != rc) {
00284         FUNC_EXIT_RC(rc);
00285     }
00286 
00287     /* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */
00288     curdata += (readBytesLen);
00289     enddata = curdata + decodedLen;
00290     if(2 != (enddata - curdata)) {
00291         FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR);
00292     }
00293 
00294     flags.all = aws_iot_mqtt_internal_read_char(&curdata);
00295     *pSessionPresent = flags.bits.sessionpresent;
00296     connack_rc_char = aws_iot_mqtt_internal_read_char(&curdata);
00297     switch(connack_rc_char) {
00298         case CONNACK_CONNECTION_ACCEPTED:
00299             *pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED;
00300             break;
00301         case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
00302             *pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
00303             break;
00304         case CONNACK_IDENTIFIER_REJECTED_ERROR:
00305             *pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR;
00306             break;
00307         case CONNACK_SERVER_UNAVAILABLE_ERROR:
00308             *pConnackRc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR;
00309             break;
00310         case CONNACK_BAD_USERDATA_ERROR:
00311             *pConnackRc = MQTT_CONNACK_BAD_USERDATA_ERROR;
00312             break;
00313         case CONNACK_NOT_AUTHORIZED_ERROR:
00314             *pConnackRc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR;
00315             break;
00316         default:
00317             *pConnackRc = MQTT_CONNACK_UNKNOWN_ERROR;
00318             break;
00319     }
00320 
00321     FUNC_EXIT_RC(IOT_SUCCESS);
00322 }
00323 
00324 /**
00325  * @brief Check if client state is valid for a connect request
00326  *
00327  * Called to check if client state is valid for a connect request
00328  * @param pClient Reference to the IoT Client
00329  *
00330  * @return bool true = state is valid, false = not valid
00331  */
00332 static bool _aws_iot_mqtt_is_client_state_valid_for_connect(ClientState clientState) {
00333     bool isValid = false;
00334 
00335     switch(clientState) {
00336         case CLIENT_STATE_INVALID:
00337             isValid = false;
00338             break;
00339         case CLIENT_STATE_INITIALIZED:
00340             isValid = true;
00341             break;
00342         case CLIENT_STATE_CONNECTING:
00343         case CLIENT_STATE_CONNECTED_IDLE:
00344         case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS:
00345         case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS:
00346         case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS:
00347         case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS:
00348         case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS:
00349         case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN:
00350         case CLIENT_STATE_DISCONNECTING:
00351             isValid = false;
00352             break;
00353         case CLIENT_STATE_DISCONNECTED_ERROR:
00354         case CLIENT_STATE_DISCONNECTED_MANUALLY:
00355         case CLIENT_STATE_PENDING_RECONNECT:
00356             isValid = true;
00357             break;
00358         default:
00359             break;
00360     }
00361 
00362     return isValid;
00363 }
00364 
00365 /**
00366  * @brief MQTT Connection Function
00367  *
00368  * Called to establish an MQTT connection with the AWS IoT Service
00369  * This is the internal function which is called by the connect API to perform the operation.
00370  * Not meant to be called directly as it doesn't do validations or client state changes
00371  *
00372  * @param pClient Reference to the IoT Client
00373  * @param pConnectParams Pointer to MQTT connection parameters
00374  *
00375  * @return An IoT Error Type defining successful/failed connection
00376  */
00377 static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) {
00378     TimerAWS connect_timer;
00379     IoT_Error_t connack_rc = IOT_FAILURE;
00380     char sessionPresent = 0;
00381     size_t len = 0;
00382     IoT_Error_t rc = IOT_FAILURE;
00383 
00384     FUNC_ENTRY;
00385 
00386     if(NULL != pConnectParams) {
00387         /* override default options if new options were supplied */
00388         rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams);
00389         if(IOT_SUCCESS != rc) {
00390             FUNC_EXIT_RC(MQTT_CONNECTION_ERROR);
00391         }
00392     }
00393 
00394     rc = pClient->networkStack.connect(&(pClient->networkStack), NULL);
00395     if(IOT_SUCCESS != rc) {
00396         /* TLS Connect failed, return error */
00397         FUNC_EXIT_RC(rc);
00398     }
00399 
00400     init_timer(&connect_timer);
00401     countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs);
00402 
00403     pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec;
00404     rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
00405                                          &(pClient->clientData.options), &len);
00406     if(IOT_SUCCESS != rc || 0 >= len) {
00407         FUNC_EXIT_RC(rc);
00408     }
00409 
00410     /* send the connect packet */
00411     rc = aws_iot_mqtt_internal_send_packet(pClient, len, &connect_timer);
00412     if(IOT_SUCCESS != rc) {
00413         FUNC_EXIT_RC(rc);
00414     }
00415 
00416     /* this will be a blocking call, wait for the CONNACK */
00417     rc = aws_iot_mqtt_internal_wait_for_read(pClient, CONNACK, &connect_timer);
00418     if(IOT_SUCCESS != rc) {
00419         FUNC_EXIT_RC(rc);
00420     }
00421 
00422     /* Received CONNACK, check the return code */
00423     rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf,
00424                                            pClient->clientData.readBufSize);
00425     if(IOT_SUCCESS != rc) {
00426         FUNC_EXIT_RC(rc);
00427     }
00428 
00429     if(MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) {
00430         FUNC_EXIT_RC(connack_rc);
00431     }
00432 
00433     pClient->clientStatus.isPingOutstanding = false;
00434     countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval);
00435 
00436     FUNC_EXIT_RC(IOT_SUCCESS);
00437 }
00438 
00439 /**
00440  * @brief MQTT Connection Function
00441  *
00442  * Called to establish an MQTT connection with the AWS IoT Service
00443  * This is the outer function which does the validations and calls the internal connect above
00444  * to perform the actual operation. It is also responsible for client state changes
00445  *
00446  * @param pClient Reference to the IoT Client
00447  * @param pConnectParams Pointer to MQTT connection parameters
00448  *
00449  * @return An IoT Error Type defining successful/failed connection
00450  */
00451 IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) {
00452     IoT_Error_t rc, disconRc;
00453     ClientState clientState;
00454 
00455     FUNC_ENTRY;
00456 
00457     if(NULL == pClient) {
00458         FUNC_EXIT_RC(NULL_VALUE_ERROR);
00459     }
00460 
00461     clientState = aws_iot_mqtt_get_client_state(pClient);
00462 
00463     if(false == _aws_iot_mqtt_is_client_state_valid_for_connect(clientState)) {
00464         /* Don't send connect packet again if we are already connected
00465          * or in the process of connecting/disconnecting */
00466         FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR);
00467     }
00468 
00469     aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTING);
00470 
00471     rc = _aws_iot_mqtt_internal_connect(pClient, pConnectParams);
00472 
00473     if(IOT_SUCCESS != rc) {
00474         pClient->networkStack.disconnect(&(pClient->networkStack));
00475         disconRc = pClient->networkStack.destroy(&(pClient->networkStack));
00476         aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_DISCONNECTED_ERROR);
00477     } else {
00478         aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED_IDLE);
00479     }
00480 
00481     FUNC_EXIT_RC(rc);
00482 }
00483 
00484 /**
00485  * @brief Disconnect an MQTT Connection
00486  *
00487  * Called to send a disconnect message to the broker.
00488  * This is the internal function which is called by the disconnect API to perform the operation.
00489  * Not meant to be called directly as it doesn't do validations or client state changes
00490  *
00491  * @param pClient Reference to the IoT Client
00492  *
00493  * @return An IoT Error Type defining successful/failed send of the disconnect control packet.
00494  */
00495 IoT_Error_t _aws_iot_mqtt_internal_disconnect(AWS_IoT_Client *pClient) {
00496     /* We might wait for incomplete incoming publishes to complete */
00497     TimerAWS timer;
00498     size_t serialized_len = 0;
00499     IoT_Error_t rc;
00500 
00501     FUNC_ENTRY;
00502 
00503     rc = aws_iot_mqtt_internal_serialize_zero(pClient->clientData.writeBuf, pClient->clientData.writeBufSize,
00504                                               DISCONNECT,
00505                                               &serialized_len);
00506     if(IOT_SUCCESS != rc) {
00507         FUNC_EXIT_RC(rc);
00508     }
00509 
00510     init_timer(&timer);
00511     countdown_ms(&timer, pClient->clientData.commandTimeoutMs);
00512 
00513     /* send the disconnect packet */
00514     if(serialized_len > 0) {
00515         rc = aws_iot_mqtt_internal_send_packet(pClient, serialized_len, &timer);
00516         if(IOT_SUCCESS != rc) {
00517             FUNC_EXIT_RC(rc);
00518         }
00519     }
00520 
00521     /* Clean network stack */
00522     pClient->networkStack.disconnect(&(pClient->networkStack));
00523     rc = pClient->networkStack.destroy(&(pClient->networkStack));
00524     if(0 != rc) {
00525         /* TLS Destroy failed, return error */
00526         FUNC_EXIT_RC(IOT_FAILURE);
00527     }
00528 
00529     FUNC_EXIT_RC(IOT_SUCCESS);
00530 }
00531 
00532 /**
00533  * @brief Disconnect an MQTT Connection
00534  *
00535  * Called to send a disconnect message to the broker.
00536  * This is the outer function which does the validations and calls the internal disconnect above
00537  * to perform the actual operation. It is also responsible for client state changes
00538  *
00539  * @param pClient Reference to the IoT Client
00540  *
00541  * @return An IoT Error Type defining successful/failed send of the disconnect control packet.
00542  */
00543 IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient) {
00544     ClientState clientState;
00545     IoT_Error_t rc;
00546 
00547     FUNC_ENTRY;
00548 
00549     if(NULL == pClient) {
00550         FUNC_EXIT_RC(NULL_VALUE_ERROR);
00551     }
00552 
00553     clientState = aws_iot_mqtt_get_client_state(pClient);
00554     if(!aws_iot_mqtt_is_client_connected(pClient)) {
00555         /* Network is already disconnected. Do nothing */
00556         FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR);
00557     }
00558 
00559     rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_DISCONNECTING);
00560     if(IOT_SUCCESS != rc) {
00561         FUNC_EXIT_RC(rc);
00562     }
00563 
00564     rc = _aws_iot_mqtt_internal_disconnect(pClient);
00565 
00566     if(IOT_SUCCESS != rc) {
00567         pClient->clientStatus.clientState = clientState;
00568     } else {
00569         /* If called from Keepalive, this gets set to CLIENT_STATE_DISCONNECTED_ERROR */
00570         pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_MANUALLY;
00571     }
00572 
00573     FUNC_EXIT_RC(rc);
00574 }
00575 
00576 /**
00577  * @brief MQTT Manual Re-Connection Function
00578  *
00579  * Called to establish an MQTT connection with the AWS IoT Service
00580  * using parameters from the last time a connection was attempted
00581  * Use after disconnect to start the reconnect process manually
00582  * Makes only one reconnect attempt. Sets the client state to
00583  * pending reconnect in case of failure
00584  *
00585  * @param pClient Reference to the IoT Client
00586  *
00587  * @return An IoT Error Type defining successful/failed connection
00588  */
00589 IoT_Error_t aws_iot_mqtt_attempt_reconnect(AWS_IoT_Client *pClient) {
00590     IoT_Error_t rc;
00591 
00592     FUNC_ENTRY;
00593 
00594     if(NULL == pClient) {
00595         FUNC_EXIT_RC(NULL_VALUE_ERROR);
00596     }
00597 
00598     if(aws_iot_mqtt_is_client_connected(pClient)) {
00599         FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR);
00600     }
00601 
00602     /* Ignoring return code. failures expected if network is disconnected */
00603     rc = aws_iot_mqtt_connect(pClient, NULL);
00604 
00605     /* If still disconnected handle disconnect */
00606     if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) {
00607         aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_DISCONNECTED_ERROR, CLIENT_STATE_PENDING_RECONNECT);
00608         FUNC_EXIT_RC(NETWORK_ATTEMPTING_RECONNECT);
00609     }
00610 
00611     rc = aws_iot_mqtt_resubscribe(pClient);
00612     if(IOT_SUCCESS != rc) {
00613         FUNC_EXIT_RC(rc);
00614     }
00615 
00616     FUNC_EXIT_RC(NETWORK_RECONNECTED);
00617 }
00618 
00619 #ifdef __cplusplus
00620 }
00621 #endif