void addToAckWaitList(uint8_t indexAckWaitList, const char *pThingName, ShadowActions_t action, const char *pExtractedClientToken, fpActionCallback_t callback, void *pCallbackContext, uint32_t timeout_seconds) { AckWaitList[indexAckWaitList].callback = callback; strncpy(AckWaitList[indexAckWaitList].clientTokenID, pExtractedClientToken, MAX_SIZE_CLIENT_ID_WITH_SEQUENCE); strncpy(AckWaitList[indexAckWaitList].thingName, pThingName, MAX_SIZE_OF_THING_NAME); AckWaitList[indexAckWaitList].pCallbackContext = pCallbackContext; AckWaitList[indexAckWaitList].action = action; init_timer(&(AckWaitList[indexAckWaitList].timer)); countdown_sec(&(AckWaitList[indexAckWaitList].timer), timeout_seconds); AckWaitList[indexAckWaitList].isFree = false; }
IoT_Error_t subscribeToShadowActionAcks(const char *pThingName, ShadowActions_t action, bool isSticky) { IoT_Error_t ret_val = SUCCESS; bool clearBothEntriesFromList = true; int16_t indexAcceptedSubList = 0; int16_t indexRejectedSubList = 0; Timer subSettlingtimer; indexAcceptedSubList = getNextFreeIndexOfSubscriptionList(); indexRejectedSubList = getNextFreeIndexOfSubscriptionList(); if(indexAcceptedSubList >= 0 && indexRejectedSubList >= 0) { topicNameFromThingAndAction(SubscriptionList[indexAcceptedSubList].Topic, pThingName, action, SHADOW_ACCEPTED); ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic), QOS0, AckStatusCallback, NULL); if(ret_val == SUCCESS) { SubscriptionList[indexAcceptedSubList].count = 1; SubscriptionList[indexAcceptedSubList].isSticky = isSticky; topicNameFromThingAndAction(SubscriptionList[indexRejectedSubList].Topic, pThingName, action, SHADOW_REJECTED); ret_val = aws_iot_mqtt_subscribe(pMqttClient, SubscriptionList[indexRejectedSubList].Topic, (uint16_t) strlen(SubscriptionList[indexRejectedSubList].Topic), QOS0, AckStatusCallback, NULL); if(ret_val == SUCCESS) { SubscriptionList[indexRejectedSubList].count = 1; SubscriptionList[indexRejectedSubList].isSticky = isSticky; clearBothEntriesFromList = false; // wait for SUBSCRIBE_SETTLING_TIME seconds to let the subscription take effect init_timer(&subSettlingtimer); countdown_sec(&subSettlingtimer, SUBSCRIBE_SETTLING_TIME); while(!has_timer_expired(&subSettlingtimer)); } } } if(clearBothEntriesFromList) { if(indexAcceptedSubList >= 0) { SubscriptionList[indexAcceptedSubList].isFree = true; } else if(indexRejectedSubList >= 0) { SubscriptionList[indexRejectedSubList].isFree = true; } if(SubscriptionList[indexAcceptedSubList].count == 1) { aws_iot_mqtt_unsubscribe(pMqttClient, SubscriptionList[indexAcceptedSubList].Topic, (uint16_t) strlen(SubscriptionList[indexAcceptedSubList].Topic)); } } return ret_val; }
/** * @brief MQTT Connection Function * * Called to establish an MQTT connection with the AWS IoT Service * This is the internal function which is called by the connect API to perform the operation. * Not meant to be called directly as it doesn't do validations or 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 */ static IoT_Error_t _aws_iot_mqtt_internal_connect(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pConnectParams) { Timer connect_timer; IoT_Error_t connack_rc = FAILURE; char sessionPresent = 0; size_t len = 0; IoT_Error_t rc = FAILURE; FUNC_ENTRY; if(NULL != pConnectParams) { /* override default options if new options were supplied */ rc = aws_iot_mqtt_set_connect_params(pClient, pConnectParams); if(SUCCESS != rc) { FUNC_EXIT_RC(MQTT_CONNECTION_ERROR); } } rc = pClient->networkStack.connect(&(pClient->networkStack), NULL); if(SUCCESS != rc) { /* TLS Connect failed, return error */ FUNC_EXIT_RC(rc); } init_timer(&connect_timer); countdown_ms(&connect_timer, pClient->clientData.commandTimeoutMs); pClient->clientData.keepAliveInterval = pClient->clientData.options.keepAliveIntervalInSec; rc = _aws_iot_mqtt_serialize_connect(pClient->clientData.writeBuf, pClient->clientData.writeBufSize, &(pClient->clientData.options), &len); if(SUCCESS != rc || 0 >= len) { FUNC_EXIT_RC(rc); } /* send the connect packet */ rc = aws_iot_mqtt_internal_send_packet(pClient, len, &connect_timer); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); } /* this will be a blocking call, wait for the CONNACK */ rc = aws_iot_mqtt_internal_wait_for_read(pClient, CONNACK, &connect_timer); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); } /* Received CONNACK, check the return code */ rc = _aws_iot_mqtt_deserialize_connack((unsigned char *) &sessionPresent, &connack_rc, pClient->clientData.readBuf, pClient->clientData.readBufSize); if(SUCCESS != rc) { FUNC_EXIT_RC(rc); } if(MQTT_CONNACK_CONNECTION_ACCEPTED != connack_rc) { FUNC_EXIT_RC(connack_rc); } pClient->clientStatus.isPingOutstanding = false; countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval); FUNC_EXIT_RC(SUCCESS); }
IoT_Error_t aws_iot_mqtt_internal_cycle_read(AWS_IoT_Client *pClient, Timer *pTimer, uint8_t *pPacketType) { IoT_Error_t rc; #ifdef _ENABLE_THREAD_SUPPORT_ IoT_Error_t threadRc; #endif if(NULL == pClient || NULL == pTimer) { return NULL_VALUE_ERROR; } #ifdef _ENABLE_THREAD_SUPPORT_ threadRc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); if(SUCCESS != threadRc) { FUNC_EXIT_RC(threadRc); } #endif /* read the socket, see what work is due */ rc = _aws_iot_mqtt_internal_read_packet(pClient, pTimer, pPacketType); #ifdef _ENABLE_THREAD_SUPPORT_ threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.tls_read_mutex)); if(SUCCESS != threadRc && (MQTT_NOTHING_TO_READ == rc || SUCCESS == rc)) { return threadRc; } #endif if(MQTT_NOTHING_TO_READ == rc) { /* Nothing to read, not a cycle failure */ return SUCCESS; } else if(SUCCESS != rc) { return rc; } switch(*pPacketType) { case CONNACK: case PUBACK: case SUBACK: case UNSUBACK: /* SDK is blocking, these responses will be forwarded to calling function to process */ break; case PUBLISH: { rc = _aws_iot_mqtt_internal_handle_publish(pClient, pTimer); break; } case PUBREC: case PUBCOMP: /* QoS2 not supported at this time */ break; case PINGRESP: { pClient->clientStatus.isPingOutstanding = 0; countdown_sec(&pClient->pingTimer, pClient->clientData.keepAliveInterval); break; } default: { /* Either unknown packet type or Failure occurred * Should not happen */ rc = MQTT_RX_MESSAGE_PACKET_TYPE_INVALID_ERROR; break; } } return rc; }