/** * @brief Disconnect an MQTT Connection * * Called to send a disconnect message to the broker. * This is the outer function which does the validations and calls the internal disconnect above * to perform the actual operation. It is also responsible for client state changes * * @param pClient Reference to the IoT Client * * @return An IoT Error Type defining successful/failed send of the disconnect control packet. */ IoT_Error_t aws_iot_mqtt_disconnect(AWS_IoT_Client *pClient) { ClientState clientState; IoT_Error_t rc; FUNC_ENTRY; if(NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } clientState = aws_iot_mqtt_get_client_state(pClient); if(!aws_iot_mqtt_is_client_connected(pClient)) { /* Network is already disconnected. Do nothing */ FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); } rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_DISCONNECTING); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); } rc = _aws_iot_mqtt_internal_disconnect(pClient); if(SUCCESS != rc) { pClient->clientStatus.clientState = clientState; } else { /* If called from Keepalive, this gets set to CLIENT_STATE_DISCONNECTED_ERROR */ pClient->clientStatus.clientState = CLIENT_STATE_DISCONNECTED_MANUALLY; } FUNC_EXIT_RC(rc); }
/** * @brief Subscribe to an MQTT topic. * * Called to send a subscribe message to the broker requesting a subscription * to an MQTT topic. * This is the outer function which does the validations and calls the internal resubscribe above * to perform the actual operation. It is also responsible for client state changes * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. * * @param pClient Reference to the IoT Client * * @return An IoT Error Type defining successful/failed subscription */ IoT_Error_t aws_iot_mqtt_resubscribe(AWS_IoT_Client *pClient) { IoT_Error_t rc, resubRc; FUNC_ENTRY; if(NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } if(false == aws_iot_mqtt_is_client_connected(pClient)) { FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); } if(CLIENT_STATE_CONNECTED_IDLE != aws_iot_mqtt_get_client_state(pClient)) { FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); } rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_IDLE, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS); if(AWS_SUCCESS != rc) { FUNC_EXIT_RC(rc); } resubRc = _aws_iot_mqtt_internal_resubscribe(pClient); rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS, CLIENT_STATE_CONNECTED_IDLE); if(AWS_SUCCESS == resubRc && AWS_SUCCESS != rc) { resubRc = rc; } FUNC_EXIT_RC(resubRc); }
/** * @brief MQTT Connection Function * * Called to establish an MQTT connection with the AWS IoT Service * This is the outer function which does the validations and calls the internal connect above * to perform the actual operation. It is also responsible for client state changes * * @param pClient Reference to the IoT Client * @param pConnectParams Pointer to MQTT connection parameters * * @return An IoT Error Type defining successful/failed connection */ IoT_Error_t aws_iot_mqtt_connect(AWS_IoT_Client *pClient, const IoT_Client_Connect_Params *pConnectParams) { IoT_Error_t rc, disconRc; ClientState clientState; FUNC_ENTRY; if(NULL == pClient) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } clientState = aws_iot_mqtt_get_client_state(pClient); if(false == _aws_iot_mqtt_is_client_state_valid_for_connect(clientState)) { /* Don't send connect packet again if we are already connected * or in the process of connecting/disconnecting */ FUNC_EXIT_RC(NETWORK_ALREADY_CONNECTED_ERROR); } aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTING); rc = _aws_iot_mqtt_internal_connect(pClient, pConnectParams); if(SUCCESS != rc) { pClient->networkStack.disconnect(&(pClient->networkStack)); disconRc = pClient->networkStack.destroy(&(pClient->networkStack)); if (SUCCESS != disconRc) { FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); } aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_DISCONNECTED_ERROR); } else { aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTING, CLIENT_STATE_CONNECTED_IDLE); } FUNC_EXIT_RC(rc); }
/** * @brief Subscribe to an MQTT topic. * * Called to send a subscribe message to the broker requesting a subscription * to an MQTT topic. This is the outer function which does the validations and * calls the internal subscribe above to perform the actual operation. * It is also responsible for client state changes * @note Call is blocking. The call returns after the receipt of the SUBACK control packet. * * @param pClient Reference to the IoT Client * @param pTopicName Topic Name to publish to * @param topicNameLen Length of the topic name * @param pApplicationHandler_t Reference to the handler function for this subscription * * @return An IoT Error Type defining successful/failed subscription */ IoT_Error_t aws_iot_mqtt_subscribe(AWS_IoT_Client *pClient, const char *pTopicName, uint16_t topicNameLen, QoS qos, pApplicationHandler_t pApplicationHandler, void *pApplicationHandlerData) { ClientState clientState; IoT_Error_t rc, subRc; FUNC_ENTRY; if(NULL == pClient || NULL == pTopicName || NULL == pApplicationHandler) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } if(!aws_iot_mqtt_is_client_connected(pClient)) { FUNC_EXIT_RC(NETWORK_DISCONNECTED_ERROR); } clientState = aws_iot_mqtt_get_client_state(pClient); if(CLIENT_STATE_CONNECTED_IDLE != clientState && CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN != clientState) { FUNC_EXIT_RC(MQTT_CLIENT_NOT_IDLE_ERROR); } rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS); if(AWS_SUCCESS != rc) { FUNC_EXIT_RC(rc); } subRc = _aws_iot_mqtt_internal_subscribe(pClient, pTopicName, topicNameLen, qos, pApplicationHandler, pApplicationHandlerData); rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS, clientState); if(AWS_SUCCESS == subRc && AWS_SUCCESS != rc) { subRc = rc; } FUNC_EXIT_RC(subRc); }
static IoT_Error_t _aws_iot_mqtt_internal_deliver_message(AWS_IoT_Client *pClient, char *pTopicName, uint16_t topicNameLen, IoT_Publish_Message_Params *pMessageParams) { uint32_t itr; IoT_Error_t rc; ClientState clientState; FUNC_ENTRY; if(NULL == pTopicName) { FUNC_EXIT_RC(NULL_VALUE_ERROR); } /* This function can be called from all MQTT APIs * But while callback return is in progress, Yield should not be called. * The state for CB_RETURN accomplishes that, as yield cannot be called while in that state */ clientState = aws_iot_mqtt_get_client_state(pClient); rc = aws_iot_mqtt_set_client_state(pClient, clientState, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN); /* Find the right message handler - indexed by topic */ for(itr = 0; itr < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++itr) { if(NULL != pClient->clientData.messageHandlers[itr].topicName) { if(((topicNameLen == pClient->clientData.messageHandlers[itr].topicNameLen) && (strncmp(pTopicName, (char *) pClient->clientData.messageHandlers[itr].topicName, topicNameLen) == 0)) || _aws_iot_mqtt_internal_is_topic_matched((char *) pClient->clientData.messageHandlers[itr].topicName, pTopicName, topicNameLen)) { if(NULL != pClient->clientData.messageHandlers[itr].pApplicationHandler) { pClient->clientData.messageHandlers[itr].pApplicationHandler(pClient, pTopicName, topicNameLen, pMessageParams, pClient->clientData.messageHandlers[itr].pApplicationHandlerData); } } } } rc = aws_iot_mqtt_set_client_state(pClient, CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN, clientState); FUNC_EXIT_RC(rc); }