| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900 |
- /*******************************************************************************
- * Copyright (c) 2009, 2024 IBM Corp., Ian Craggs and others
- *
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v2.0
- * and Eclipse Distribution License v1.0 which accompany this distribution.
- *
- * The Eclipse Public License is available at
- * https://www.eclipse.org/legal/epl-2.0/
- * and the Eclipse Distribution License is available at
- * http://www.eclipse.org/org/documents/edl-v10.php.
- *
- * Contributors:
- * Ian Craggs - initial implementation and documentation
- * Ian Craggs, Allan Stockdill-Mander - SSL support
- * Ian Craggs - multiple server connection support
- * Ian Craggs - fix for bug 413429 - connectionLost not called
- * Ian Craggs - fix for bug 415042 - using already freed structure
- * Ian Craggs - fix for bug 419233 - mutexes not reporting errors
- * Ian Craggs - fix for bug 420851
- * Ian Craggs - fix for bug 432903 - queue persistence
- * Ian Craggs - MQTT 3.1.1 support
- * Rong Xiang, Ian Craggs - C++ compatibility
- * Ian Craggs - fix for bug 442400: reconnecting after network cable unplugged
- * Ian Craggs - fix for bug 444934 - incorrect free in freeCommand1
- * Ian Craggs - fix for bug 445891 - assigning msgid is not thread safe
- * Ian Craggs - fix for bug 465369 - longer latency than expected
- * Ian Craggs - fix for bug 444103 - success/failure callbacks not invoked
- * Ian Craggs - fix for bug 484363 - segfault in getReadySocket
- * Ian Craggs - automatic reconnect and offline buffering (send while disconnected)
- * Ian Craggs - fix for bug 472250
- * Ian Craggs - fix for bug 486548
- * Ian Craggs - SNI support
- * Ian Craggs - auto reconnect timing fix #218
- * Ian Craggs - fix for issue #190
- * Ian Craggs - check for NULL SSL options #334
- * Ian Craggs - allocate username/password buffers #431
- * Ian Craggs - MQTT 5.0 support
- * Ian Craggs - refactor to reduce module size
- *******************************************************************************/
- #include <stdlib.h>
- #include <string.h>
- #if !defined(_WIN32) && !defined(_WIN64)
- #include <sys/time.h>
- #else
- #if defined(_MSC_VER) && _MSC_VER < 1900
- #define snprintf _snprintf
- #endif
- #endif
- #if !defined(NO_PERSISTENCE)
- #include "MQTTPersistence.h"
- #endif
- #include "MQTTAsync.h"
- #include "MQTTAsyncUtils.h"
- #include "utf-8.h"
- #include "MQTTProtocol.h"
- #include "MQTTProtocolOut.h"
- #include "Thread.h"
- #include "SocketBuffer.h"
- #include "StackTrace.h"
- #include "Heap.h"
- #include "OsWrapper.h"
- #include "WebSocket.h"
- static void MQTTAsync_freeServerURIs(MQTTAsyncs* m);
- #include "VersionInfo.h"
- const char *client_timestamp_eye = "MQTTAsyncV3_Timestamp " BUILD_TIMESTAMP;
- const char *client_version_eye = "MQTTAsyncV3_Version " CLIENT_VERSION;
- volatile int global_initialized = 0;
- List* MQTTAsync_handles = NULL;
- List* MQTTAsync_commands = NULL;
- int MQTTAsync_tostop = 0;
- static ClientStates ClientState =
- {
- CLIENT_VERSION, /* version */
- NULL /* client list */
- };
- MQTTProtocol state;
- ClientStates* bstate = &ClientState;
- enum MQTTAsync_threadStates sendThread_state = STOPPED;
- enum MQTTAsync_threadStates receiveThread_state = STOPPED;
- thread_id_type sendThread_id = 0,
- receiveThread_id = 0;
- // global objects init declaration
- int MQTTAsync_init(void);
- void MQTTAsync_global_init(MQTTAsync_init_options* inits)
- {
- MQTTAsync_init();
- #if defined(OPENSSL)
- SSLSocket_handleOpensslInit(inits->do_openssl_init);
- #endif
- }
- #if !defined(min)
- #define min(a, b) (((a) < (b)) ? (a) : (b))
- #endif
- #if defined(WIN32) || defined(WIN64)
- void MQTTAsync_init_rand(void)
- {
- START_TIME_TYPE now = MQTTTime_start_clock();
- srand((unsigned int)now);
- }
- #elif defined(AIX)
- void MQTTAsync_init_rand(void)
- {
- START_TIME_TYPE now = MQTTTime_start_clock();
- srand(now.tv_nsec);
- }
- #else
- void MQTTAsync_init_rand(void)
- {
- START_TIME_TYPE now = MQTTTime_start_clock();
- srand(now.tv_usec);
- }
- #endif
- #if defined(_WIN32) || defined(_WIN64)
- mutex_type mqttasync_mutex = NULL;
- mutex_type socket_mutex = NULL;
- mutex_type mqttcommand_mutex = NULL;
- sem_type send_sem = NULL;
- #if !defined(NO_HEAP_TRACKING)
- extern mutex_type stack_mutex;
- extern mutex_type heap_mutex;
- #endif
- extern mutex_type log_mutex;
- int MQTTAsync_init(void)
- {
- DWORD rc = 0;
- if (mqttasync_mutex == NULL)
- {
- if ((mqttasync_mutex = CreateMutex(NULL, 0, NULL)) == NULL)
- {
- rc = GetLastError();
- printf("mqttasync_mutex error %d\n", rc);
- goto exit;
- }
- if ((mqttcommand_mutex = CreateMutex(NULL, 0, NULL)) == NULL)
- {
- rc = GetLastError();
- printf("mqttcommand_mutex error %d\n", rc);
- goto exit;
- }
- if ((send_sem = CreateEvent(
- NULL, /* default security attributes */
- FALSE, /* manual-reset event? */
- FALSE, /* initial state is nonsignaled */
- NULL /* object name */
- )) == NULL)
- {
- rc = GetLastError();
- printf("send_sem error %d\n", rc);
- goto exit;
- }
- #if !defined(NO_HEAP_TRACKING)
- if ((stack_mutex = CreateMutex(NULL, 0, NULL)) == NULL)
- {
- rc = GetLastError();
- printf("stack_mutex error %d\n", rc);
- goto exit;
- }
- if ((heap_mutex = CreateMutex(NULL, 0, NULL)) == NULL)
- {
- rc = GetLastError();
- printf("heap_mutex error %d\n", rc);
- goto exit;
- }
- #endif
- if ((log_mutex = CreateMutex(NULL, 0, NULL)) == NULL)
- {
- rc = GetLastError();
- printf("log_mutex error %d\n", rc);
- goto exit;
- }
- if ((socket_mutex = CreateMutex(NULL, 0, NULL)) == NULL)
- {
- rc = GetLastError();
- printf("socket_mutex error %d\n", rc);
- goto exit;
- }
- }
- else
- {
- Log(TRACE_MAX, -1, "Library already initialized");
- }
- exit:
- return rc;
- }
- void MQTTAsync_cleanup(void)
- {
- if (send_sem)
- CloseHandle(send_sem);
- #if !defined(NO_HEAP_TRACKING)
- if (stack_mutex)
- CloseHandle(stack_mutex);
- if (heap_mutex)
- CloseHandle(heap_mutex);
- #endif
- if (log_mutex)
- CloseHandle(log_mutex);
- if (socket_mutex)
- CloseHandle(socket_mutex);
- if (mqttasync_mutex)
- CloseHandle(mqttasync_mutex);
- }
- #if defined(PAHO_MQTT_STATIC)
- static INIT_ONCE g_InitOnce = INIT_ONCE_STATIC_INIT; /* Global for one time initialization */
- /* This runs at most once */
- BOOL CALLBACK InitMutexesOnce (
- PINIT_ONCE InitOnce, /* Pointer to one-time initialization structure */
- PVOID Parameter, /* Optional parameter */
- PVOID *lpContext) /* Return data, if any */
- {
- int rc = MQTTAsync_init();
- return rc == 0;
- }
- #else
- BOOL APIENTRY DllMain(HANDLE hModule,
- DWORD ul_reason_for_call,
- LPVOID lpReserved)
- {
- switch (ul_reason_for_call)
- {
- case DLL_PROCESS_ATTACH:
- MQTTAsync_init();
- break;
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- break;
- case DLL_PROCESS_DETACH:
- if (lpReserved)
- MQTTAsync_cleanup();
- break;
- }
- return TRUE;
- }
- #endif
- #else
- static pthread_mutex_t mqttasync_mutex_store = PTHREAD_MUTEX_INITIALIZER;
- mutex_type mqttasync_mutex = &mqttasync_mutex_store;
- static pthread_mutex_t socket_mutex_store = PTHREAD_MUTEX_INITIALIZER;
- mutex_type socket_mutex = &socket_mutex_store;
- static pthread_mutex_t mqttcommand_mutex_store = PTHREAD_MUTEX_INITIALIZER;
- mutex_type mqttcommand_mutex = &mqttcommand_mutex_store;
- static cond_type_struct send_cond_store = { PTHREAD_COND_INITIALIZER, PTHREAD_MUTEX_INITIALIZER };
- cond_type send_cond = &send_cond_store;
- int MQTTAsync_init(void)
- {
- pthread_mutexattr_t attr;
- int rc;
- pthread_mutexattr_init(&attr);
- #if !defined(_WRS_KERNEL)
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
- #else
- /* #warning "no pthread_mutexattr_settype" */
- #endif
- if ((rc = pthread_mutex_init(mqttasync_mutex, &attr)) != 0)
- printf("MQTTAsync: error %d initializing async_mutex\n", rc);
- else if ((rc = pthread_mutex_init(mqttcommand_mutex, &attr)) != 0)
- printf("MQTTAsync: error %d initializing command_mutex\n", rc);
- else if ((rc = pthread_mutex_init(socket_mutex, &attr)) != 0)
- printf("MQTTClient: error %d initializing socket_mutex\n", rc);
- else if ((rc = pthread_cond_init(&send_cond->cond, NULL)) != 0)
- printf("MQTTAsync: error %d initializing send_cond cond\n", rc);
- else if ((rc = pthread_mutex_init(&send_cond->mutex, &attr)) != 0)
- printf("MQTTAsync: error %d initializing send_cond mutex\n", rc);
- return rc;
- }
- #endif
- int MQTTAsync_createWithOptions(MQTTAsync* handle, const char* serverURI, const char* clientId,
- int persistence_type, void* persistence_context, MQTTAsync_createOptions* options)
- {
- int rc = 0;
- MQTTAsyncs *m = NULL;
- #if (defined(_WIN32) || defined(_WIN64)) && defined(PAHO_MQTT_STATIC)
- /* intializes mutexes once. Must come before FUNC_ENTRY */
- BOOL bStatus = InitOnceExecuteOnce(&g_InitOnce, InitMutexesOnce, NULL, NULL);
- #endif
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (serverURI == NULL || clientId == NULL)
- {
- rc = MQTTASYNC_NULL_PARAMETER;
- goto exit;
- }
- if (!UTF8_validateString(clientId))
- {
- rc = MQTTASYNC_BAD_UTF8_STRING;
- goto exit;
- }
- if (strlen(clientId) == 0 && persistence_type == MQTTCLIENT_PERSISTENCE_DEFAULT)
- {
- rc = MQTTASYNC_PERSISTENCE_ERROR;
- goto exit;
- }
- if (strstr(serverURI, "://") != NULL)
- {
- if (strncmp(URI_TCP, serverURI, strlen(URI_TCP)) != 0
- && strncmp(URI_MQTT, serverURI, strlen(URI_MQTT)) != 0
- #if defined(UNIXSOCK)
- && strncmp(URI_UNIX, serverURI, strlen(URI_UNIX)) != 0
- #endif
- && strncmp(URI_WS, serverURI, strlen(URI_WS)) != 0
- #if defined(OPENSSL)
- && strncmp(URI_SSL, serverURI, strlen(URI_SSL)) != 0
- && strncmp(URI_MQTTS, serverURI, strlen(URI_MQTTS)) != 0
- && strncmp(URI_WSS, serverURI, strlen(URI_WSS)) != 0
- #endif
- )
- {
- rc = MQTTASYNC_BAD_PROTOCOL;
- goto exit;
- }
- }
- if (options && options->maxBufferedMessages <= 0)
- {
- rc = MQTTASYNC_MAX_BUFFERED;
- goto exit;
- }
- if (options && (strncmp(options->struct_id, "MQCO", 4) != 0 ||
- options->struct_version < 0 || options->struct_version > 3))
- {
- rc = MQTTASYNC_BAD_STRUCTURE;
- goto exit;
- }
- if (!global_initialized)
- {
- #if !defined(NO_HEAP_TRACKING)
- Heap_initialize();
- #endif
- Log_initialize((Log_nameValue*)MQTTAsync_getVersionInfo());
- bstate->clients = ListInitialize();
- Socket_outInitialize();
- Socket_setWriteContinueCallback(MQTTAsync_writeContinue);
- Socket_setWriteCompleteCallback(MQTTAsync_writeComplete);
- Socket_setWriteAvailableCallback(MQTTProtocol_writeAvailable);
- MQTTAsync_handles = ListInitialize();
- MQTTAsync_commands = ListInitialize();
- #if defined(OPENSSL)
- SSLSocket_initialize();
- #endif
- global_initialized = 1;
- }
- if ((m = malloc(sizeof(MQTTAsyncs))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- *handle = m;
- memset(m, '\0', sizeof(MQTTAsyncs));
- if (strncmp(URI_TCP, serverURI, strlen(URI_TCP)) == 0)
- serverURI += strlen(URI_TCP);
- else if (strncmp(URI_MQTT, serverURI, strlen(URI_MQTT)) == 0)
- serverURI += strlen(URI_MQTT);
- #if defined(UNIXSOCK)
- else if (strncmp(URI_UNIX, serverURI, strlen(URI_UNIX)) == 0)
- {
- serverURI += strlen(URI_UNIX);
- m->unixsock = 1;
- }
- #endif
- else if (strncmp(URI_WS, serverURI, strlen(URI_WS)) == 0)
- {
- serverURI += strlen(URI_WS);
- m->websocket = 1;
- }
- #if defined(OPENSSL)
- else if (strncmp(URI_SSL, serverURI, strlen(URI_SSL)) == 0)
- {
- serverURI += strlen(URI_SSL);
- m->ssl = 1;
- }
- else if (strncmp(URI_MQTTS, serverURI, strlen(URI_MQTTS)) == 0)
- {
- serverURI += strlen(URI_MQTTS);
- m->ssl = 1;
- }
- else if (strncmp(URI_WSS, serverURI, strlen(URI_WSS)) == 0)
- {
- serverURI += strlen(URI_WSS);
- m->ssl = 1;
- m->websocket = 1;
- }
- #endif
- if ((m->serverURI = MQTTStrdup(serverURI)) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- m->responses = ListInitialize();
- ListAppend(MQTTAsync_handles, m, sizeof(MQTTAsyncs));
- if ((m->c = malloc(sizeof(Clients))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(m->c, '\0', sizeof(Clients));
- m->c->context = m;
- m->c->outboundMsgs = ListInitialize();
- m->c->inboundMsgs = ListInitialize();
- m->c->messageQueue = ListInitialize();
- m->c->outboundQueue = ListInitialize();
- m->c->clientID = MQTTStrdup(clientId);
- if (m->c->context == NULL || m->c->outboundMsgs == NULL || m->c->inboundMsgs == NULL ||
- m->c->messageQueue == NULL || m->c->outboundQueue == NULL || m->c->clientID == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- m->c->MQTTVersion = MQTTVERSION_DEFAULT;
- m->shouldBeConnected = 0;
- if (options)
- {
- if ((m->createOptions = malloc(sizeof(MQTTAsync_createOptions))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memcpy(m->createOptions, options, sizeof(MQTTAsync_createOptions));
- if (options->struct_version > 0)
- m->c->MQTTVersion = options->MQTTVersion;
- }
- #if !defined(NO_PERSISTENCE)
- rc = MQTTPersistence_create(&(m->c->persistence), persistence_type, persistence_context);
- if (rc == 0)
- {
- rc = MQTTPersistence_initialize(m->c, m->serverURI); /* inflight messages restored here */
- if (rc == 0)
- {
- if (m->createOptions && m->createOptions->struct_version >= 2 && m->createOptions->restoreMessages == 0)
- MQTTAsync_unpersistCommandsAndMessages(m->c);
- else
- {
- MQTTAsync_restoreCommands(m);
- MQTTPersistence_restoreMessageQueue(m->c);
- }
- }
- }
- #endif
- ListAppend(bstate->clients, m->c, sizeof(Clients) + 3*sizeof(List));
- exit:
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_create(MQTTAsync* handle, const char* serverURI, const char* clientId,
- int persistence_type, void* persistence_context)
- {
- MQTTAsync_init_rand();
- return MQTTAsync_createWithOptions(handle, serverURI, clientId, persistence_type,
- persistence_context, NULL);
- }
- void MQTTAsync_destroy(MQTTAsync* handle)
- {
- MQTTAsyncs* m = *handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL)
- goto exit;
- MQTTAsync_closeSession(m->c, MQTTREASONCODE_SUCCESS, NULL);
- MQTTAsync_NULLPublishResponses(m);
- MQTTAsync_freeResponses(m);
- MQTTAsync_freeCommands(m);
- ListFree(m->responses);
- if (m->c)
- {
- SOCKET saved_socket = m->c->net.socket;
- char* saved_clientid = MQTTStrdup(m->c->clientID);
- #if !defined(NO_PERSISTENCE)
- MQTTPersistence_close(m->c);
- #endif
- MQTTAsync_emptyMessageQueue(m->c);
- MQTTProtocol_freeClient(m->c);
- if (!ListRemove(bstate->clients, m->c))
- Log(LOG_ERROR, 0, NULL);
- else
- Log(TRACE_MIN, 1, NULL, saved_clientid, saved_socket);
- free(saved_clientid);
- }
- if (m->serverURI)
- free(m->serverURI);
- if (m->createOptions)
- free(m->createOptions);
- MQTTAsync_freeServerURIs(m);
- if (m->connectProps)
- {
- MQTTProperties_free(m->connectProps);
- free(m->connectProps);
- m->connectProps = NULL;
- }
- if (m->willProps)
- {
- MQTTProperties_free(m->willProps);
- free(m->willProps);
- m->willProps = NULL;
- }
- if (!ListRemove(MQTTAsync_handles, m))
- Log(LOG_ERROR, -1, "free error");
- *handle = NULL;
- if (bstate->clients->count == 0)
- MQTTAsync_terminate();
- exit:
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT;
- }
- int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options)
- {
- MQTTAsyncs* m = handle;
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsync_queuedCommand* conn;
- thread_id_type thread_id = 0;
- int locked = 0;
- FUNC_ENTRY;
- if (options == NULL)
- {
- rc = MQTTASYNC_NULL_PARAMETER;
- goto exit;
- }
- if (strncmp(options->struct_id, "MQTC", 4) != 0 || options->struct_version < 0 || options->struct_version > 8)
- {
- rc = MQTTASYNC_BAD_STRUCTURE;
- goto exit;
- }
- #if defined(OPENSSL)
- if (m->ssl && options->ssl == NULL)
- {
- rc = MQTTASYNC_NULL_PARAMETER;
- goto exit;
- }
- #endif
- if (options->will) /* check validity of will options structure */
- {
- if (strncmp(options->will->struct_id, "MQTW", 4) != 0 || (options->will->struct_version != 0 && options->will->struct_version != 1))
- {
- rc = MQTTASYNC_BAD_STRUCTURE;
- goto exit;
- }
- if (options->will->qos < 0 || options->will->qos > 2)
- {
- rc = MQTTASYNC_BAD_QOS;
- goto exit;
- }
- if (options->will->topicName == NULL)
- {
- rc = MQTTASYNC_NULL_PARAMETER;
- goto exit;
- } else if (strlen(options->will->topicName) == 0)
- {
- rc = MQTTASYNC_0_LEN_WILL_TOPIC;
- goto exit;
- }
- }
- if (options->struct_version != 0 && options->ssl) /* check validity of SSL options structure */
- {
- if (strncmp(options->ssl->struct_id, "MQTS", 4) != 0 || options->ssl->struct_version < 0 || options->ssl->struct_version > 5)
- {
- rc = MQTTASYNC_BAD_STRUCTURE;
- goto exit;
- }
- }
- if (options->MQTTVersion >= MQTTVERSION_5 && m->c->MQTTVersion < MQTTVERSION_5)
- {
- rc = MQTTASYNC_WRONG_MQTT_VERSION;
- goto exit;
- }
- if ((options->username && !UTF8_validateString(options->username)) ||
- (options->password && !UTF8_validateString(options->password)))
- {
- rc = MQTTASYNC_BAD_UTF8_STRING;
- goto exit;
- }
- if (options->MQTTVersion >= MQTTVERSION_5 && options->struct_version < 6)
- {
- rc = MQTTASYNC_BAD_STRUCTURE;
- goto exit;
- }
- if (options->MQTTVersion >= MQTTVERSION_5 && options->cleansession != 0)
- {
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- goto exit;
- }
- if (options->MQTTVersion < MQTTVERSION_5 && options->struct_version >= 6)
- {
- if (options->cleanstart != 0 || options->onFailure5 || options->onSuccess5 ||
- options->connectProperties || options->willProperties)
- {
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- goto exit;
- }
- }
- m->connect.onSuccess = options->onSuccess;
- m->connect.onFailure = options->onFailure;
- if (options->struct_version >= 6)
- {
- m->connect.onSuccess5 = options->onSuccess5;
- m->connect.onFailure5 = options->onFailure5;
- }
- m->connect.context = options->context;
- m->connectTimeout = options->connectTimeout;
- /* don't lock async mutex if we are being called from a callback */
- thread_id = Paho_thread_getid();
- if (thread_id != sendThread_id && thread_id != receiveThread_id)
- {
- MQTTAsync_lock_mutex(mqttasync_mutex);
- locked = 1;
- }
- MQTTAsync_tostop = 0;
- if (sendThread_state != STARTING && sendThread_state != RUNNING)
- {
- sendThread_state = STARTING;
- Paho_thread_start(MQTTAsync_sendThread, NULL);
- }
- if (receiveThread_state != STARTING && receiveThread_state != RUNNING)
- {
- receiveThread_state = STARTING;
- Paho_thread_start(MQTTAsync_receiveThread, handle);
- }
- if (locked)
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- m->c->keepAliveInterval = m->c->savedKeepAliveInterval = options->keepAliveInterval;
- setRetryLoopInterval(options->keepAliveInterval);
- m->c->cleansession = options->cleansession;
- m->c->maxInflightMessages = options->maxInflight;
- if (options->struct_version >= 3)
- m->c->MQTTVersion = options->MQTTVersion;
- else
- m->c->MQTTVersion = MQTTVERSION_DEFAULT;
- if (options->struct_version >= 4)
- {
- m->automaticReconnect = options->automaticReconnect;
- m->minRetryInterval = options->minRetryInterval;
- m->maxRetryInterval = options->maxRetryInterval;
- }
- if (options->struct_version >= 7)
- {
- m->c->net.httpHeaders = (const MQTTClient_nameValue *) options->httpHeaders;
- }
- if (options->struct_version >= 8)
- {
- if (options->httpProxy)
- m->c->httpProxy = MQTTStrdup(options->httpProxy);
- if (options->httpsProxy)
- m->c->httpsProxy = MQTTStrdup(options->httpsProxy);
- }
- if (m->c->will)
- {
- free(m->c->will->payload);
- free(m->c->will->topic);
- free(m->c->will);
- m->c->will = NULL;
- }
- if (options->will && (options->will->struct_version == 0 || options->will->struct_version == 1))
- {
- const void* source = NULL;
- if ((m->c->will = malloc(sizeof(willMessages))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- if (options->will->message || (options->will->struct_version == 1 && options->will->payload.data))
- {
- if (options->will->struct_version == 1 && options->will->payload.data)
- {
- m->c->will->payloadlen = options->will->payload.len;
- source = options->will->payload.data;
- }
- else
- {
- m->c->will->payloadlen = (int)strlen(options->will->message);
- source = (void*)options->will->message;
- }
- if ((m->c->will->payload = malloc(m->c->will->payloadlen)) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memcpy(m->c->will->payload, source, m->c->will->payloadlen);
- }
- else
- {
- m->c->will->payload = NULL;
- m->c->will->payloadlen = 0;
- }
- m->c->will->qos = options->will->qos;
- m->c->will->retained = options->will->retained;
- m->c->will->topic = MQTTStrdup(options->will->topicName);
- }
- #if defined(OPENSSL)
- if (m->c->sslopts)
- {
- if (m->c->sslopts->trustStore)
- free((void*)m->c->sslopts->trustStore);
- if (m->c->sslopts->keyStore)
- free((void*)m->c->sslopts->keyStore);
- if (m->c->sslopts->privateKey)
- free((void*)m->c->sslopts->privateKey);
- if (m->c->sslopts->privateKeyPassword)
- free((void*)m->c->sslopts->privateKeyPassword);
- if (m->c->sslopts->enabledCipherSuites)
- free((void*)m->c->sslopts->enabledCipherSuites);
- if (m->c->sslopts->struct_version >= 2)
- {
- if (m->c->sslopts->CApath)
- free((void*)m->c->sslopts->CApath);
- }
- free((void*)m->c->sslopts);
- m->c->sslopts = NULL;
- }
- if (options->struct_version != 0 && options->ssl)
- {
- if ((m->c->sslopts = malloc(sizeof(MQTTClient_SSLOptions))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(m->c->sslopts, '\0', sizeof(MQTTClient_SSLOptions));
- m->c->sslopts->struct_version = options->ssl->struct_version;
- if (options->ssl->trustStore)
- m->c->sslopts->trustStore = MQTTStrdup(options->ssl->trustStore);
- if (options->ssl->keyStore)
- m->c->sslopts->keyStore = MQTTStrdup(options->ssl->keyStore);
- if (options->ssl->privateKey)
- m->c->sslopts->privateKey = MQTTStrdup(options->ssl->privateKey);
- if (options->ssl->privateKeyPassword)
- m->c->sslopts->privateKeyPassword = MQTTStrdup(options->ssl->privateKeyPassword);
- if (options->ssl->enabledCipherSuites)
- m->c->sslopts->enabledCipherSuites = MQTTStrdup(options->ssl->enabledCipherSuites);
- m->c->sslopts->enableServerCertAuth = options->ssl->enableServerCertAuth;
- if (m->c->sslopts->struct_version >= 1)
- m->c->sslopts->sslVersion = options->ssl->sslVersion;
- if (m->c->sslopts->struct_version >= 2)
- {
- m->c->sslopts->verify = options->ssl->verify;
- if (options->ssl->CApath)
- m->c->sslopts->CApath = MQTTStrdup(options->ssl->CApath);
- }
- if (m->c->sslopts->struct_version >= 3)
- {
- m->c->sslopts->ssl_error_cb = options->ssl->ssl_error_cb;
- m->c->sslopts->ssl_error_context = options->ssl->ssl_error_context;
- }
- if (m->c->sslopts->struct_version >= 4)
- {
- m->c->sslopts->ssl_psk_cb = options->ssl->ssl_psk_cb;
- m->c->sslopts->ssl_psk_context = options->ssl->ssl_psk_context;
- m->c->sslopts->disableDefaultTrustStore = options->ssl->disableDefaultTrustStore;
- }
- if (m->c->sslopts->struct_version >= 5)
- {
- if (options->ssl->protos)
- m->c->sslopts->protos = (const unsigned char*)MQTTStrdup((const char*)options->ssl->protos);
- m->c->sslopts->protos_len = options->ssl->protos_len;
- }
- }
- #else
- if (options->struct_version != 0 && options->ssl)
- {
- rc = MQTTASYNC_SSL_NOT_SUPPORTED;
- goto exit;
- }
- #endif
- if (m->c->username)
- {
- free((void*)m->c->username);
- m->c->username = NULL;
- }
- if (options->username)
- m->c->username = MQTTStrdup(options->username);
- if (m->c->password)
- {
- free((void*)m->c->password);
- m->c->password = NULL;
- }
- if (options->password)
- {
- m->c->password = MQTTStrdup(options->password);
- m->c->passwordlen = (int)strlen(options->password);
- }
- else if (options->struct_version >= 5 && options->binarypwd.data)
- {
- m->c->passwordlen = options->binarypwd.len;
- if ((m->c->password = malloc(m->c->passwordlen)) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memcpy((void*)m->c->password, options->binarypwd.data, m->c->passwordlen);
- }
- m->c->retryInterval = options->retryInterval;
- m->shouldBeConnected = 1;
- m->connectTimeout = options->connectTimeout;
- MQTTAsync_freeServerURIs(m);
- if (options->struct_version >= 2 && options->serverURIcount > 0)
- {
- int i;
- m->serverURIcount = options->serverURIcount;
- if ((m->serverURIs = malloc(options->serverURIcount * sizeof(char*))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- for (i = 0; i < options->serverURIcount; ++i)
- m->serverURIs[i] = MQTTStrdup(options->serverURIs[i]);
- }
- if (m->connectProps)
- {
- MQTTProperties_free(m->connectProps);
- free(m->connectProps);
- m->connectProps = NULL;
- }
- if (m->willProps)
- {
- MQTTProperties_free(m->willProps);
- free(m->willProps);
- m->willProps = NULL;
- }
- if (options->struct_version >=6)
- {
- if (options->connectProperties)
- {
- MQTTProperties initialized = MQTTProperties_initializer;
- if ((m->connectProps = malloc(sizeof(MQTTProperties))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- *m->connectProps = initialized;
- *m->connectProps = MQTTProperties_copy(options->connectProperties);
- if (MQTTProperties_hasProperty(options->connectProperties, MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL))
- m->c->sessionExpiry = (int)MQTTProperties_getNumericValue(options->connectProperties,
- MQTTPROPERTY_CODE_SESSION_EXPIRY_INTERVAL);
- }
- if (options->willProperties)
- {
- MQTTProperties initialized = MQTTProperties_initializer;
- if ((m->willProps = malloc(sizeof(MQTTProperties))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- *m->willProps = initialized;
- *m->willProps = MQTTProperties_copy(options->willProperties);
- }
- m->c->cleanstart = options->cleanstart;
- }
- /* Add connect request to operation queue */
- if ((conn = malloc(sizeof(MQTTAsync_queuedCommand))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(conn, '\0', sizeof(MQTTAsync_queuedCommand));
- conn->client = m;
- if (options)
- {
- conn->command.onSuccess = options->onSuccess;
- conn->command.onFailure = options->onFailure;
- conn->command.onSuccess5 = options->onSuccess5;
- conn->command.onFailure5 = options->onFailure5;
- conn->command.context = options->context;
- }
- conn->command.type = CONNECT;
- conn->command.details.conn.currentURI = 0;
- rc = MQTTAsync_addCommand(conn, sizeof(conn));
- exit:
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_reconnect(MQTTAsync handle)
- {
- int rc = MQTTASYNC_FAILURE;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m->automaticReconnect)
- {
- if (m->shouldBeConnected)
- {
- m->reconnectNow = 1;
- m->currentIntervalBase = m->minRetryInterval;
- m->currentInterval = m->minRetryInterval;
- m->retrying = 1;
- rc = MQTTASYNC_SUCCESS;
- }
- }
- else
- {
- /* to reconnect, put the connect command to the head of the command queue */
- MQTTAsync_queuedCommand* conn = malloc(sizeof(MQTTAsync_queuedCommand));
- if (!conn)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(conn, '\0', sizeof(MQTTAsync_queuedCommand));
- conn->client = m;
- conn->command = m->connect;
- /* make sure that the version attempts are restarted */
- if (m->c->MQTTVersion == MQTTVERSION_DEFAULT)
- conn->command.details.conn.MQTTVersion = 0;
- rc = MQTTAsync_addCommand(conn, sizeof(m->connect));
- }
- exit:
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_inCallback()
- {
- thread_id_type thread_id = Paho_thread_getid();
- return thread_id == sendThread_id || thread_id == receiveThread_id;
- }
- int MQTTAsync_subscribeMany(MQTTAsync handle, int count, char* const* topic, const int* qos, MQTTAsync_responseOptions* response)
- {
- MQTTAsyncs* m = handle;
- int i = 0;
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsync_queuedCommand* sub;
- int msgid = 0;
- FUNC_ENTRY;
- if (!MQTTAsync_inCallback())
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c == NULL)
- rc = MQTTASYNC_FAILURE;
- else if (m->c->connected == 0)
- rc = MQTTASYNC_DISCONNECTED;
- else for (i = 0; i < count; i++)
- {
- if (!UTF8_validateString(topic[i]))
- {
- rc = MQTTASYNC_BAD_UTF8_STRING;
- break;
- }
- if (qos[i] < 0 || qos[i] > 2)
- {
- rc = MQTTASYNC_BAD_QOS;
- break;
- }
- }
- if (rc != MQTTASYNC_SUCCESS)
- ; /* don't overwrite a previous error code */
- else if ((msgid = MQTTAsync_assignMsgId(m)) == 0)
- rc = MQTTASYNC_NO_MORE_MSGIDS;
- else if (m->c->MQTTVersion >= MQTTVERSION_5 && count > 1 && (count != response->subscribeOptionsCount
- && response->subscribeOptionsCount != 0))
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- else if (response)
- {
- if (m->c->MQTTVersion >= MQTTVERSION_5)
- {
- if (response->struct_version == 0 || response->onFailure || response->onSuccess)
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- }
- else if (m->c->MQTTVersion < MQTTVERSION_5)
- {
- if (response->struct_version >= 1 && (response->onFailure5 || response->onSuccess5))
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- }
- }
- if (rc != MQTTASYNC_SUCCESS)
- goto exit;
- /* Add subscribe request to operation queue */
- if ((sub = malloc(sizeof(MQTTAsync_queuedCommand))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(sub, '\0', sizeof(MQTTAsync_queuedCommand));
- sub->client = m;
- sub->command.token = msgid;
- if (response)
- {
- sub->command.onSuccess = response->onSuccess;
- sub->command.onFailure = response->onFailure;
- sub->command.onSuccess5 = response->onSuccess5;
- sub->command.onFailure5 = response->onFailure5;
- sub->command.context = response->context;
- response->token = sub->command.token;
- if (m->c->MQTTVersion >= MQTTVERSION_5)
- {
- sub->command.properties = MQTTProperties_copy(&response->properties);
- sub->command.details.sub.opts = response->subscribeOptions;
- if (count > 1)
- {
- if ((sub->command.details.sub.optlist = malloc(sizeof(MQTTSubscribe_options) * count)) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- if (response->subscribeOptionsCount == 0)
- {
- MQTTSubscribe_options initialized = MQTTSubscribe_options_initializer;
- for (i = 0; i < count; ++i)
- sub->command.details.sub.optlist[i] = initialized;
- }
- else
- {
- for (i = 0; i < count; ++i)
- sub->command.details.sub.optlist[i] = response->subscribeOptionsList[i];
- }
- }
- }
- }
- sub->command.type = SUBSCRIBE;
- sub->command.details.sub.count = count;
- sub->command.details.sub.topics = malloc(sizeof(char*) * count);
- sub->command.details.sub.qoss = malloc(sizeof(int) * count);
- if (sub->command.details.sub.topics && sub->command.details.sub.qoss)
- {
- for (i = 0; i < count; ++i)
- {
- if ((sub->command.details.sub.topics[i] = MQTTStrdup(topic[i])) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- sub->command.details.sub.qoss[i] = qos[i];
- }
- rc = MQTTAsync_addCommand(sub, sizeof(sub));
- }
- else
- rc = PAHO_MEMORY_ERROR;
- exit:
- if (!MQTTAsync_inCallback())
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_subscribe(MQTTAsync handle, const char* topic, int qos, MQTTAsync_responseOptions* response)
- {
- int rc = 0;
- FUNC_ENTRY;
- rc = MQTTAsync_subscribeMany(handle, 1, (char * const *)(&topic), &qos, response);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_unsubscribeMany(MQTTAsync handle, int count, char* const* topic, MQTTAsync_responseOptions* response)
- {
- MQTTAsyncs* m = handle;
- int i = 0;
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsync_queuedCommand* unsub;
- int msgid = 0;
- FUNC_ENTRY;
- if (!MQTTAsync_inCallback())
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c == NULL)
- rc = MQTTASYNC_FAILURE;
- else if (m->c->connected == 0)
- rc = MQTTASYNC_DISCONNECTED;
- else for (i = 0; i < count; i++)
- {
- if (!UTF8_validateString(topic[i]))
- {
- rc = MQTTASYNC_BAD_UTF8_STRING;
- break;
- }
- }
- if (rc != MQTTASYNC_SUCCESS)
- ; /* don't overwrite a previous error code */
- else if ((msgid = MQTTAsync_assignMsgId(m)) == 0)
- rc = MQTTASYNC_NO_MORE_MSGIDS;
- else if (response)
- {
- if (m->c->MQTTVersion >= MQTTVERSION_5)
- {
- if (response->struct_version == 0 || response->onFailure || response->onSuccess)
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- }
- else if (m->c->MQTTVersion < MQTTVERSION_5)
- {
- if (response->struct_version >= 1 && (response->onFailure5 || response->onSuccess5))
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- }
- }
- if (rc != MQTTASYNC_SUCCESS)
- goto exit;
- /* Add unsubscribe request to operation queue */
- if ((unsub = malloc(sizeof(MQTTAsync_queuedCommand))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(unsub, '\0', sizeof(MQTTAsync_queuedCommand));
- unsub->client = m;
- unsub->command.type = UNSUBSCRIBE;
- unsub->command.token = msgid;
- if (response)
- {
- unsub->command.onSuccess = response->onSuccess;
- unsub->command.onFailure = response->onFailure;
- unsub->command.onSuccess5 = response->onSuccess5;
- unsub->command.onFailure5 = response->onFailure5;
- unsub->command.context = response->context;
- response->token = unsub->command.token;
- if (m->c->MQTTVersion >= MQTTVERSION_5)
- unsub->command.properties = MQTTProperties_copy(&response->properties);
- }
- unsub->command.details.unsub.count = count;
- if ((unsub->command.details.unsub.topics = malloc(sizeof(char*) * count)) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- for (i = 0; i < count; ++i)
- unsub->command.details.unsub.topics[i] = MQTTStrdup(topic[i]);
- rc = MQTTAsync_addCommand(unsub, sizeof(unsub));
- exit:
- if (!MQTTAsync_inCallback())
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_unsubscribe(MQTTAsync handle, const char* topic, MQTTAsync_responseOptions* response)
- {
- int rc = 0;
- FUNC_ENTRY;
- rc = MQTTAsync_unsubscribeMany(handle, 1, (char * const *)(&topic), response);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_send(MQTTAsync handle, const char* destinationName, int payloadlen, const void* payload,
- int qos, int retained, MQTTAsync_responseOptions* response)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- MQTTAsync_queuedCommand* pub;
- int msgid = 0;
- FUNC_ENTRY;
- if (!MQTTAsync_inCallback())
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c == NULL)
- rc = MQTTASYNC_FAILURE;
- else if (m->c->connected == 0)
- {
- if (m->createOptions == NULL)
- rc = MQTTASYNC_DISCONNECTED;
- else if (m->createOptions->sendWhileDisconnected == 0)
- rc = MQTTASYNC_DISCONNECTED;
- else if (m->shouldBeConnected == 0 && (m->createOptions->struct_version < 2 || m->createOptions->allowDisconnectedSendAtAnyTime == 0))
- rc = MQTTASYNC_DISCONNECTED;
- }
- if (rc != MQTTASYNC_SUCCESS)
- goto exit;
- if (!UTF8_validateString(destinationName))
- rc = MQTTASYNC_BAD_UTF8_STRING;
- else if (qos < 0 || qos > 2)
- rc = MQTTASYNC_BAD_QOS;
- else if (qos > 0 && (msgid = MQTTAsync_assignMsgId(m)) == 0)
- rc = MQTTASYNC_NO_MORE_MSGIDS;
- else if (m->createOptions &&
- (m->createOptions->struct_version < 2 || m->createOptions->deleteOldestMessages == 0) &&
- (MQTTAsync_getNoBufferedMessages(m) >= m->createOptions->maxBufferedMessages))
- rc = MQTTASYNC_MAX_BUFFERED_MESSAGES;
- else if (response)
- {
- if (m->c->MQTTVersion >= MQTTVERSION_5)
- {
- if (response->struct_version == 0 || response->onFailure || response->onSuccess)
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- }
- else if (m->c->MQTTVersion < MQTTVERSION_5)
- {
- if (response->struct_version >= 1 && (response->onFailure5 || response->onSuccess5))
- rc = MQTTASYNC_BAD_MQTT_OPTION;
- }
- }
- if (rc != MQTTASYNC_SUCCESS)
- goto exit;
- /* Add publish request to operation queue */
- if ((pub = malloc(sizeof(MQTTAsync_queuedCommand))) == NULL)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memset(pub, '\0', sizeof(MQTTAsync_queuedCommand));
- pub->client = m;
- pub->command.type = PUBLISH;
- pub->command.token = msgid;
- if (response)
- {
- pub->command.onSuccess = response->onSuccess;
- pub->command.onFailure = response->onFailure;
- pub->command.onSuccess5 = response->onSuccess5;
- pub->command.onFailure5 = response->onFailure5;
- pub->command.context = response->context;
- response->token = pub->command.token;
- if (m->c->MQTTVersion >= MQTTVERSION_5)
- pub->command.properties = MQTTProperties_copy(&response->properties);
- }
- if ((pub->command.details.pub.destinationName = MQTTStrdup(destinationName)) == NULL)
- {
- free(pub);
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- pub->command.details.pub.payloadlen = payloadlen;
- if ((pub->command.details.pub.payload = malloc(payloadlen)) == NULL)
- {
- free(pub->command.details.pub.destinationName);
- free(pub);
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- memcpy(pub->command.details.pub.payload, payload, payloadlen);
- pub->command.details.pub.qos = qos;
- pub->command.details.pub.retained = retained;
- rc = MQTTAsync_addCommand(pub, sizeof(pub));
- exit:
- if (!MQTTAsync_inCallback())
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_sendMessage(MQTTAsync handle, const char* destinationName, const MQTTAsync_message* message,
- MQTTAsync_responseOptions* response)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- if (message == NULL)
- {
- rc = MQTTASYNC_NULL_PARAMETER;
- goto exit;
- }
- if (strncmp(message->struct_id, "MQTM", 4) != 0 ||
- (message->struct_version != 0 && message->struct_version != 1))
- {
- rc = MQTTASYNC_BAD_STRUCTURE;
- goto exit;
- }
- if (m->c->MQTTVersion >= MQTTVERSION_5 && response)
- response->properties = message->properties;
- rc = MQTTAsync_send(handle, destinationName, message->payloadlen, message->payload,
- message->qos, message->retained, response);
- exit:
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_disconnect(MQTTAsync handle, const MQTTAsync_disconnectOptions* options)
- {
- int rc = 0;
- FUNC_ENTRY;
- if (!MQTTAsync_inCallback())
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (options != NULL && (strncmp(options->struct_id, "MQTD", 4) != 0 || options->struct_version < 0 || options->struct_version > 1))
- rc = MQTTASYNC_BAD_STRUCTURE;
- else
- rc = MQTTAsync_disconnect1(handle, options, 0);
- if (!MQTTAsync_inCallback())
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_isConnected(MQTTAsync handle)
- {
- MQTTAsyncs* m = handle;
- int rc = 0;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m && m->c)
- rc = m->c->connected;
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_isComplete(MQTTAsync handle, MQTTAsync_token dt)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- ListElement* current = NULL;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL)
- {
- rc = MQTTASYNC_FAILURE;
- goto exit;
- }
- /* First check unprocessed commands */
- current = NULL;
- while (ListNextElement(MQTTAsync_commands, ¤t))
- {
- MQTTAsync_queuedCommand* cmd = (MQTTAsync_queuedCommand*)(current->content);
- if (cmd->client == m && cmd->command.token == dt)
- goto exit;
- }
- /* Now check the inflight messages */
- if (m->c && m->c->outboundMsgs->count > 0)
- {
- current = NULL;
- while (ListNextElement(m->c->outboundMsgs, ¤t))
- {
- Messages* m2 = (Messages*)(current->content);
- if (m2->msgid == dt)
- goto exit;
- }
- }
- rc = MQTTASYNC_TRUE; /* Can't find it, so it must be complete */
- exit:
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_waitForCompletion(MQTTAsync handle, MQTTAsync_token dt, unsigned long timeout)
- {
- int rc = MQTTASYNC_FAILURE;
- START_TIME_TYPE start = MQTTTime_start_clock();
- ELAPSED_TIME_TYPE elapsed = 0L;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c == NULL)
- {
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- rc = MQTTASYNC_FAILURE;
- goto exit;
- }
- if (m->c->connected == 0)
- {
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- rc = MQTTASYNC_DISCONNECTED;
- goto exit;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- if (MQTTAsync_isComplete(handle, dt) == 1)
- {
- rc = MQTTASYNC_SUCCESS; /* well we couldn't find it */
- goto exit;
- }
- elapsed = MQTTTime_elapsed(start);
- while (elapsed < timeout && rc == MQTTASYNC_FAILURE)
- {
- MQTTTime_sleep(100);
- if (MQTTAsync_isComplete(handle, dt) == 1)
- rc = MQTTASYNC_SUCCESS; /* well we couldn't find it */
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m->c->connected == 0)
- rc = MQTTASYNC_DISCONNECTED;
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- elapsed = MQTTTime_elapsed(start);
- }
- exit:
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_getPendingTokens(MQTTAsync handle, MQTTAsync_token **tokens)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- ListElement* current = NULL;
- int count = 0;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- MQTTAsync_lock_mutex(mqttcommand_mutex);
- *tokens = NULL;
- if (m == NULL)
- {
- rc = MQTTASYNC_FAILURE;
- goto exit;
- }
- /* calculate the number of pending tokens - commands plus inflight */
- while (ListNextElement(MQTTAsync_commands, ¤t))
- {
- MQTTAsync_queuedCommand* cmd = (MQTTAsync_queuedCommand*)(current->content);
- if (cmd->client == m && cmd->command.type == PUBLISH)
- count++;
- }
- if (m->c)
- count += m->c->outboundMsgs->count;
- if (count == 0)
- goto exit; /* no tokens to return */
- *tokens = malloc(sizeof(MQTTAsync_token) * (count + 1)); /* add space for sentinel at end of list */
- if (!*tokens)
- {
- rc = PAHO_MEMORY_ERROR;
- goto exit;
- }
- /* First add the unprocessed commands to the pending tokens */
- current = NULL;
- count = 0;
- while (ListNextElement(MQTTAsync_commands, ¤t))
- {
- MQTTAsync_queuedCommand* cmd = (MQTTAsync_queuedCommand*)(current->content);
- if (cmd->client == m && cmd->command.type == PUBLISH)
- (*tokens)[count++] = cmd->command.token;
- }
- /* Now add the inflight messages */
- if (m->c && m->c->outboundMsgs->count > 0)
- {
- current = NULL;
- while (ListNextElement(m->c->outboundMsgs, ¤t))
- {
- Messages* m2 = (Messages*)(current->content);
- (*tokens)[count++] = m2->msgid;
- }
- }
- (*tokens)[count] = -1; /* indicate end of list */
- exit:
- MQTTAsync_unlock_mutex(mqttcommand_mutex);
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setCallbacks(MQTTAsync handle, void* context,
- MQTTAsync_connectionLost* cl,
- MQTTAsync_messageArrived* ma,
- MQTTAsync_deliveryComplete* dc)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || ma == NULL || m->c == NULL || m->c->connect_state != NOT_IN_PROGRESS)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->clContext = m->maContext = m->dcContext = context;
- m->cl = cl;
- m->ma = ma;
- m->dc = dc;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setConnectionLostCallback(MQTTAsync handle, void* context,
- MQTTAsync_connectionLost* cl)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c->connect_state != 0)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->clContext = context;
- m->cl = cl;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setMessageArrivedCallback(MQTTAsync handle, void* context,
- MQTTAsync_messageArrived* ma)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || ma == NULL || m->c->connect_state != 0)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->maContext = context;
- m->ma = ma;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setDeliveryCompleteCallback(MQTTAsync handle, void* context,
- MQTTAsync_deliveryComplete* dc)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c->connect_state != 0)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->dcContext = context;
- m->dc = dc;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setDisconnected(MQTTAsync handle, void* context, MQTTAsync_disconnected* disconnected)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c->connect_state != NOT_IN_PROGRESS)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->disconnected_context = context;
- m->disconnected = disconnected;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setConnected(MQTTAsync handle, void* context, MQTTAsync_connected* connected)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL || m->c->connect_state != NOT_IN_PROGRESS)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->connected_context = context;
- m->connected = connected;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setUpdateConnectOptions(MQTTAsync handle, void* context, MQTTAsync_updateConnectOptions* updateOptions)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->updateConnectOptions_context = context;
- m->updateConnectOptions = updateOptions;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- #if !defined(NO_PERSISTENCE)
- int MQTTAsync_setBeforePersistenceWrite(MQTTAsync handle, void* context, MQTTPersistence_beforeWrite* co)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->c->beforeWrite = co;
- m->c->beforeWrite_context = context;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- int MQTTAsync_setAfterPersistenceRead(MQTTAsync handle, void* context, MQTTPersistence_afterRead* co)
- {
- int rc = MQTTASYNC_SUCCESS;
- MQTTAsyncs* m = handle;
- FUNC_ENTRY;
- MQTTAsync_lock_mutex(mqttasync_mutex);
- if (m == NULL)
- rc = MQTTASYNC_FAILURE;
- else
- {
- m->c->afterRead = co;
- m->c->afterRead_context = context;
- }
- MQTTAsync_unlock_mutex(mqttasync_mutex);
- FUNC_EXIT_RC(rc);
- return rc;
- }
- #endif
- void MQTTAsync_setTraceLevel(enum MQTTASYNC_TRACE_LEVELS level)
- {
- Log_setTraceLevel((enum LOG_LEVELS)level);
- }
- void MQTTAsync_setTraceCallback(MQTTAsync_traceCallback* callback)
- {
- Log_setTraceCallback((Log_traceCallback*)callback);
- }
- MQTTAsync_nameValue* MQTTAsync_getVersionInfo(void)
- {
- #define MAX_INFO_STRINGS 8
- static MQTTAsync_nameValue libinfo[MAX_INFO_STRINGS + 1];
- int i = 0;
- libinfo[i].name = "Product name";
- libinfo[i++].value = "Eclipse Paho Asynchronous MQTT C Client Library";
- libinfo[i].name = "Version";
- libinfo[i++].value = CLIENT_VERSION;
- libinfo[i].name = "Build level";
- libinfo[i++].value = BUILD_TIMESTAMP;
- #if defined(OPENSSL)
- libinfo[i].name = "OpenSSL version";
- libinfo[i++].value = SSLeay_version(SSLEAY_VERSION);
- libinfo[i].name = "OpenSSL flags";
- libinfo[i++].value = SSLeay_version(SSLEAY_CFLAGS);
- libinfo[i].name = "OpenSSL build timestamp";
- libinfo[i++].value = SSLeay_version(SSLEAY_BUILT_ON);
- libinfo[i].name = "OpenSSL platform";
- libinfo[i++].value = SSLeay_version(SSLEAY_PLATFORM);
- libinfo[i].name = "OpenSSL directory";
- libinfo[i++].value = SSLeay_version(SSLEAY_DIR);
- #endif
- libinfo[i].name = NULL;
- libinfo[i].value = NULL;
- return libinfo;
- }
- const char* MQTTAsync_strerror(int code)
- {
- static char buf[30];
- int chars = 0;
- switch (code) {
- case MQTTASYNC_SUCCESS:
- return "Success";
- case MQTTASYNC_FAILURE:
- return "Failure";
- case MQTTASYNC_PERSISTENCE_ERROR:
- return "Persistence error";
- case MQTTASYNC_DISCONNECTED:
- return "Disconnected";
- case MQTTASYNC_MAX_MESSAGES_INFLIGHT:
- return "Maximum in-flight messages amount reached";
- case MQTTASYNC_BAD_UTF8_STRING:
- return "Invalid UTF8 string";
- case MQTTASYNC_NULL_PARAMETER:
- return "Invalid (NULL) parameter";
- case MQTTASYNC_TOPICNAME_TRUNCATED:
- return "Topic containing NULL characters has been truncated";
- case MQTTASYNC_BAD_STRUCTURE:
- return "Bad structure";
- case MQTTASYNC_BAD_QOS:
- return "Invalid QoS value";
- case MQTTASYNC_NO_MORE_MSGIDS:
- return "Too many pending commands";
- case MQTTASYNC_OPERATION_INCOMPLETE:
- return "Operation discarded before completion";
- case MQTTASYNC_MAX_BUFFERED_MESSAGES:
- return "No more messages can be buffered";
- case MQTTASYNC_SSL_NOT_SUPPORTED:
- return "SSL is not supported";
- case MQTTASYNC_BAD_PROTOCOL:
- return "Invalid protocol scheme";
- case MQTTASYNC_BAD_MQTT_OPTION:
- return "Options for wrong MQTT version";
- case MQTTASYNC_WRONG_MQTT_VERSION:
- return "Client created for another version of MQTT";
- case MQTTASYNC_0_LEN_WILL_TOPIC:
- return "Zero length will topic on connect";
- case MQTTASYNC_COMMAND_IGNORED:
- return "Connect or disconnect command ignored";
- case MQTTASYNC_MAX_BUFFERED:
- return "maxBufferedMessages in the connect options must be >= 0";
- }
- chars = snprintf(buf, sizeof(buf), "Unknown error code %d", code);
- if (chars >= sizeof(buf))
- {
- buf[sizeof(buf)-1] = '\0';
- Log(LOG_ERROR, 0, "Error writing %d chars with snprintf", chars);
- }
- return buf;
- }
- void MQTTAsync_freeMessage(MQTTAsync_message** message)
- {
- FUNC_ENTRY;
- MQTTProperties_free(&(*message)->properties);
- free((*message)->payload);
- free(*message);
- *message = NULL;
- FUNC_EXIT;
- }
- void MQTTAsync_free(void* memory)
- {
- FUNC_ENTRY;
- free(memory);
- FUNC_EXIT;
- }
- void* MQTTAsync_malloc(size_t size)
- {
- void* val;
- int rc = 0;
- FUNC_ENTRY;
- val = malloc(size);
- rc = (val != NULL);
- FUNC_EXIT_RC(rc);
- return val;
- }
- static void MQTTAsync_freeServerURIs(MQTTAsyncs* m)
- {
- int i;
- for (i = 0; i < m->serverURIcount; ++i)
- free(m->serverURIs[i]);
- m->serverURIcount = 0;
- if (m->serverURIs)
- free(m->serverURIs);
- m->serverURIs = NULL;
- }
|