Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
aws_iot_mqtt_client.c
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 * Allan Stockdill-Mander/Ian Craggs - initial API and implementation and/or initial documentation 00031 *******************************************************************************/ 00032 00033 /** 00034 * @file aws_iot_mqtt_client.c 00035 * @brief MQTT client API definitions 00036 */ 00037 00038 #ifdef __cplusplus 00039 extern "C" { 00040 #endif 00041 00042 #include <string.h> 00043 00044 #include "aws_iot_log.h" 00045 #include "aws_iot_mqtt_client_interface.h" 00046 #include "aws_iot_version.h" 00047 00048 #if !DISABLE_METRICS 00049 #define SDK_METRICS_LEN 25 00050 #define SDK_METRICS_TEMPLATE "?SDK=C&Version=%d.%d.%d" 00051 static char pUsernameTemp[SDK_METRICS_LEN] = {0}; 00052 #endif 00053 00054 #ifdef _ENABLE_THREAD_SUPPORT_ 00055 #include "threads_interface.h" 00056 #endif 00057 00058 const IoT_Client_Init_Params iotClientInitParamsDefault = IoT_Client_Init_Params_initializer; 00059 const IoT_MQTT_Will_Options iotMqttWillOptionsDefault = IoT_MQTT_Will_Options_Initializer; 00060 const IoT_Client_Connect_Params iotClientConnectParamsDefault = IoT_Client_Connect_Params_initializer; 00061 00062 ClientState aws_iot_mqtt_get_client_state(AWS_IoT_Client *pClient) { 00063 FUNC_ENTRY; 00064 if(NULL == pClient) { 00065 return CLIENT_STATE_INVALID; 00066 } 00067 00068 FUNC_EXIT_RC(pClient->clientStatus.clientState); 00069 } 00070 00071 #ifdef _ENABLE_THREAD_SUPPORT_ 00072 IoT_Error_t aws_iot_mqtt_client_lock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { 00073 FUNC_ENTRY; 00074 IoT_Error_t threadRc = FAILURE; 00075 00076 if(NULL == pClient || NULL == pMutex){ 00077 FUNC_EXIT_RC(NULL_VALUE_ERROR); 00078 } 00079 00080 if(false == pClient->clientData.isBlockOnThreadLockEnabled) { 00081 threadRc = aws_iot_thread_mutex_trylock(pMutex); 00082 } else { 00083 threadRc = aws_iot_thread_mutex_lock(pMutex); 00084 /* Should never return Error because the above request blocks until lock is obtained */ 00085 } 00086 00087 if(AWS_SUCCESS != threadRc) { 00088 FUNC_EXIT_RC(threadRc); 00089 } 00090 00091 FUNC_EXIT_RC(AWS_SUCCESS); 00092 } 00093 00094 IoT_Error_t aws_iot_mqtt_client_unlock_mutex(AWS_IoT_Client *pClient, IoT_Mutex_t *pMutex) { 00095 if(NULL == pClient || NULL == pMutex) { 00096 return NULL_VALUE_ERROR; 00097 } 00098 IOT_UNUSED(pClient); 00099 return aws_iot_thread_mutex_unlock(pMutex); 00100 } 00101 #endif 00102 00103 IoT_Error_t aws_iot_mqtt_set_client_state(AWS_IoT_Client *pClient, ClientState expectedCurrentState, 00104 ClientState newState) { 00105 IoT_Error_t rc; 00106 #ifdef _ENABLE_THREAD_SUPPORT_ 00107 IoT_Error_t threadRc = FAILURE; 00108 #endif 00109 00110 FUNC_ENTRY; 00111 if(NULL == pClient) { 00112 FUNC_EXIT_RC(NULL_VALUE_ERROR); 00113 } 00114 00115 #ifdef _ENABLE_THREAD_SUPPORT_ 00116 rc = aws_iot_mqtt_client_lock_mutex(pClient, &(pClient->clientData.state_change_mutex)); 00117 if(AWS_SUCCESS != rc) { 00118 return rc; 00119 } 00120 #endif 00121 if(expectedCurrentState == aws_iot_mqtt_get_client_state(pClient)) { 00122 pClient->clientStatus.clientState = newState; 00123 rc = AWS_SUCCESS; 00124 } else { 00125 rc = MQTT_UNEXPECTED_CLIENT_STATE_ERROR; 00126 } 00127 00128 #ifdef _ENABLE_THREAD_SUPPORT_ 00129 threadRc = aws_iot_mqtt_client_unlock_mutex(pClient, &(pClient->clientData.state_change_mutex)); 00130 if(AWS_SUCCESS == rc && AWS_SUCCESS != threadRc) { 00131 rc = threadRc; 00132 } 00133 #endif 00134 00135 FUNC_EXIT_RC(rc); 00136 } 00137 00138 IoT_Error_t aws_iot_mqtt_set_connect_params(AWS_IoT_Client *pClient, IoT_Client_Connect_Params *pNewConnectParams) { 00139 FUNC_ENTRY; 00140 if(NULL == pClient || NULL == pNewConnectParams) { 00141 FUNC_EXIT_RC(NULL_VALUE_ERROR); 00142 } 00143 00144 pClient->clientData.options.isWillMsgPresent = pNewConnectParams->isWillMsgPresent; 00145 pClient->clientData.options.MQTTVersion = pNewConnectParams->MQTTVersion; 00146 pClient->clientData.options.pClientID = pNewConnectParams->pClientID; 00147 pClient->clientData.options.clientIDLen = pNewConnectParams->clientIDLen; 00148 #if !DISABLE_METRICS 00149 if (0 == strlen(pUsernameTemp)) { 00150 snprintf(pUsernameTemp, SDK_METRICS_LEN, SDK_METRICS_TEMPLATE, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); 00151 } 00152 pClient->clientData.options.pUsername = (char*)&pUsernameTemp[0]; 00153 pClient->clientData.options.usernameLen = strlen(pUsernameTemp); 00154 #else 00155 pClient->clientData.options.pUsername = pNewConnectParams->pUsername; 00156 pClient->clientData.options.usernameLen = pNewConnectParams->usernameLen; 00157 #endif 00158 pClient->clientData.options.pPassword = pNewConnectParams->pPassword; 00159 pClient->clientData.options.passwordLen = pNewConnectParams->passwordLen; 00160 pClient->clientData.options.will.pTopicName = pNewConnectParams->will.pTopicName; 00161 pClient->clientData.options.will.topicNameLen = pNewConnectParams->will.topicNameLen; 00162 pClient->clientData.options.will.pMessage = pNewConnectParams->will.pMessage; 00163 pClient->clientData.options.will.msgLen = pNewConnectParams->will.msgLen; 00164 pClient->clientData.options.will.qos = pNewConnectParams->will.qos; 00165 pClient->clientData.options.will.isRetained = pNewConnectParams->will.isRetained; 00166 pClient->clientData.options.keepAliveIntervalInSec = pNewConnectParams->keepAliveIntervalInSec; 00167 pClient->clientData.options.isCleanSession = pNewConnectParams->isCleanSession; 00168 00169 FUNC_EXIT_RC(AWS_SUCCESS); 00170 } 00171 00172 IoT_Error_t aws_iot_mqtt_free(AWS_IoT_Client *pClient) 00173 { 00174 IoT_Error_t rc = AWS_SUCCESS; 00175 00176 if (NULL == pClient) { 00177 rc = NULL_VALUE_ERROR; 00178 }else 00179 { 00180 #ifdef _ENABLE_THREAD_SUPPORT_ 00181 if (rc == AWS_SUCCESS) 00182 { 00183 rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); 00184 } 00185 00186 if (rc == AWS_SUCCESS) 00187 { 00188 rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); 00189 }else{ 00190 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); 00191 } 00192 00193 if (rc == AWS_SUCCESS) 00194 { 00195 rc = aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); 00196 }else{ 00197 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); 00198 } 00199 #endif 00200 } 00201 00202 FUNC_EXIT_RC(rc); 00203 } 00204 00205 IoT_Error_t aws_iot_mqtt_init(AWS_IoT_Client *pClient, IoT_Client_Init_Params *pInitParams) { 00206 uint32_t i; 00207 IoT_Error_t rc; 00208 IoT_Client_Connect_Params default_options = IoT_Client_Connect_Params_initializer; 00209 FUNC_ENTRY; 00210 00211 if(NULL == pClient || NULL == pInitParams || NULL == pInitParams->pHostURL || 0 == pInitParams->port || 00212 NULL == pInitParams->pRootCALocation || NULL == pInitParams->pDevicePrivateKeyLocation || 00213 NULL == pInitParams->pDeviceCertLocation) { 00214 FUNC_EXIT_RC(NULL_VALUE_ERROR); 00215 } 00216 00217 for(i = 0; i < AWS_IOT_MQTT_NUM_SUBSCRIBE_HANDLERS; ++i) { 00218 pClient->clientData.messageHandlers[i].topicName = NULL; 00219 pClient->clientData.messageHandlers[i].pApplicationHandler = NULL; 00220 pClient->clientData.messageHandlers[i].pApplicationHandlerData = NULL; 00221 pClient->clientData.messageHandlers[i].qos = QOS0; 00222 } 00223 00224 pClient->clientData.packetTimeoutMs = pInitParams->mqttPacketTimeout_ms; 00225 pClient->clientData.commandTimeoutMs = pInitParams->mqttCommandTimeout_ms; 00226 pClient->clientData.writeBufSize = AWS_IOT_MQTT_TX_BUF_LEN; 00227 pClient->clientData.readBufSize = AWS_IOT_MQTT_RX_BUF_LEN; 00228 pClient->clientData.counterNetworkDisconnected = 0; 00229 pClient->clientData.disconnectHandler = pInitParams->disconnectHandler; 00230 pClient->clientData.disconnectHandlerData = pInitParams->disconnectHandlerData; 00231 pClient->clientData.nextPacketId = 1; 00232 00233 pClient->clientData.packetTimeoutMs = pInitParams->mqttPacketTimeout_ms; 00234 /* Initialize default connection options */ 00235 rc = aws_iot_mqtt_set_connect_params(pClient, &default_options); 00236 if(AWS_SUCCESS != rc) { 00237 FUNC_EXIT_RC(rc); 00238 } 00239 00240 #ifdef _ENABLE_THREAD_SUPPORT_ 00241 pClient->clientData.isBlockOnThreadLockEnabled = pInitParams->isBlockOnThreadLockEnabled; 00242 rc = aws_iot_thread_mutex_init(&(pClient->clientData.state_change_mutex)); 00243 if(AWS_SUCCESS != rc) { 00244 FUNC_EXIT_RC(rc); 00245 } 00246 rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_read_mutex)); 00247 if(AWS_SUCCESS != rc) { 00248 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); 00249 FUNC_EXIT_RC(rc); 00250 } 00251 rc = aws_iot_thread_mutex_init(&(pClient->clientData.tls_write_mutex)); 00252 if(AWS_SUCCESS != rc) { 00253 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); 00254 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); 00255 FUNC_EXIT_RC(rc); 00256 } 00257 #endif 00258 00259 pClient->clientStatus.isPingOutstanding = 0; 00260 pClient->clientStatus.isAutoReconnectEnabled = pInitParams->enableAutoReconnect; 00261 00262 rc = iot_tls_init(&(pClient->networkStack), pInitParams->pRootCALocation, pInitParams->pDeviceCertLocation, 00263 pInitParams->pDevicePrivateKeyLocation, pInitParams->pHostURL, pInitParams->port, 00264 pInitParams->tlsHandshakeTimeout_ms, pInitParams->isSSLHostnameVerify); 00265 00266 if(AWS_SUCCESS != rc) { 00267 #ifdef _ENABLE_THREAD_SUPPORT_ 00268 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_read_mutex)); 00269 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.state_change_mutex)); 00270 (void)aws_iot_thread_mutex_destroy(&(pClient->clientData.tls_write_mutex)); 00271 #endif 00272 pClient->clientStatus.clientState = CLIENT_STATE_INVALID; 00273 FUNC_EXIT_RC(rc); 00274 } 00275 00276 init_timer(&(pClient->pingTimer)); 00277 init_timer(&(pClient->reconnectDelayTimer)); 00278 00279 pClient->clientStatus.clientState = CLIENT_STATE_INITIALIZED; 00280 00281 FUNC_EXIT_RC(AWS_SUCCESS); 00282 } 00283 00284 uint16_t aws_iot_mqtt_get_next_packet_id(AWS_IoT_Client *pClient) { 00285 return pClient->clientData.nextPacketId = (uint16_t) ((MAX_PACKET_ID == pClient->clientData.nextPacketId) ? 1 : ( 00286 pClient->clientData.nextPacketId + 1)); 00287 } 00288 00289 bool aws_iot_mqtt_is_client_connected(AWS_IoT_Client *pClient) { 00290 bool isConnected; 00291 00292 FUNC_ENTRY; 00293 00294 if(NULL == pClient) { 00295 IOT_WARN(" Client is null! "); 00296 FUNC_EXIT_RC(false); 00297 } 00298 00299 switch(pClient->clientStatus.clientState) { 00300 case CLIENT_STATE_INVALID: 00301 case CLIENT_STATE_INITIALIZED: 00302 case CLIENT_STATE_CONNECTING: 00303 isConnected = false; 00304 break; 00305 case CLIENT_STATE_CONNECTED_IDLE: 00306 case CLIENT_STATE_CONNECTED_YIELD_IN_PROGRESS: 00307 case CLIENT_STATE_CONNECTED_PUBLISH_IN_PROGRESS: 00308 case CLIENT_STATE_CONNECTED_SUBSCRIBE_IN_PROGRESS: 00309 case CLIENT_STATE_CONNECTED_UNSUBSCRIBE_IN_PROGRESS: 00310 case CLIENT_STATE_CONNECTED_RESUBSCRIBE_IN_PROGRESS: 00311 case CLIENT_STATE_CONNECTED_WAIT_FOR_CB_RETURN: 00312 isConnected = true; 00313 break; 00314 case CLIENT_STATE_DISCONNECTING: 00315 case CLIENT_STATE_DISCONNECTED_ERROR: 00316 case CLIENT_STATE_DISCONNECTED_MANUALLY: 00317 case CLIENT_STATE_PENDING_RECONNECT: 00318 default: 00319 isConnected = false; 00320 break; 00321 } 00322 00323 FUNC_EXIT_RC(isConnected); 00324 } 00325 00326 bool aws_iot_is_autoreconnect_enabled(AWS_IoT_Client *pClient) { 00327 FUNC_ENTRY; 00328 if(NULL == pClient) { 00329 IOT_WARN(" Client is null! "); 00330 FUNC_EXIT_RC(false); 00331 } 00332 00333 FUNC_EXIT_RC(pClient->clientStatus.isAutoReconnectEnabled); 00334 } 00335 00336 IoT_Error_t aws_iot_mqtt_autoreconnect_set_status(AWS_IoT_Client *pClient, bool newStatus) { 00337 FUNC_ENTRY; 00338 if(NULL == pClient) { 00339 FUNC_EXIT_RC(NULL_VALUE_ERROR); 00340 } 00341 pClient->clientStatus.isAutoReconnectEnabled = newStatus; 00342 FUNC_EXIT_RC(AWS_SUCCESS); 00343 } 00344 00345 IoT_Error_t aws_iot_mqtt_set_disconnect_handler(AWS_IoT_Client *pClient, iot_disconnect_handler pDisconnectHandler, 00346 void *pDisconnectHandlerData) { 00347 FUNC_ENTRY; 00348 if(NULL == pClient || NULL == pDisconnectHandler) { 00349 FUNC_EXIT_RC(NULL_VALUE_ERROR); 00350 } 00351 00352 pClient->clientData.disconnectHandler = pDisconnectHandler; 00353 pClient->clientData.disconnectHandlerData = pDisconnectHandlerData; 00354 FUNC_EXIT_RC(AWS_SUCCESS); 00355 } 00356 00357 uint32_t aws_iot_mqtt_get_network_disconnected_count(AWS_IoT_Client *pClient) { 00358 return pClient->clientData.counterNetworkDisconnected; 00359 } 00360 00361 void aws_iot_mqtt_reset_network_disconnected_count(AWS_IoT_Client *pClient) { 00362 pClient->clientData.counterNetworkDisconnected = 0; 00363 } 00364 00365 #ifdef __cplusplus 00366 } 00367 #endif 00368
Generated on Tue Jul 12 2022 19:02:38 by
1.7.2