Jim Flynn / Mbed OS aws-iot-device-sdk-mbed-c
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aws_iot_mqtt_client_connect.c Source File

aws_iot_mqtt_client_connect.c

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