diff --git a/src/Clients.h b/src/Clients.h index 67489582..577551ee 100644 --- a/src/Clients.h +++ b/src/Clients.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2023 IBM Corp. and Ian Craggs + * Copyright (c) 2009, 2024 IBM Corp. and Ian Craggs * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 @@ -114,8 +114,9 @@ typedef struct /** * Data related to one client + * The entire structure is initialized to 0 on creation, so all fields default to 0. */ -typedef struct +typedef struct Clients { char* clientID; /**< the string id of the client */ const char* username; /**< MQTT v3.1 user name */ @@ -132,6 +133,7 @@ typedef struct networkHandles net; /**< network info for this client */ int msgID; /**< the MQTT message id */ int keepAliveInterval; /**< the MQTT keep alive interval */ + int savedKeepAliveInterval; /**< saved keep alive interval, in case reset by server keep alive */ int retryInterval; /**< the MQTT retry interval for QoS > 0 */ int maxInflightMessages; /**< the max number of inflight outbound messages we allow */ willMessages* will; /**< the MQTT will message, if any */ diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index c6a11f6d..8ab3d5fc 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2023 IBM Corp., Ian Craggs and others + * 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 @@ -668,7 +668,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) if (locked) MQTTAsync_unlock_mutex(mqttasync_mutex); - m->c->keepAliveInterval = options->keepAliveInterval; + m->c->keepAliveInterval = m->c->savedKeepAliveInterval = options->keepAliveInterval; setRetryLoopInterval(options->keepAliveInterval); m->c->cleansession = options->cleansession; m->c->maxInflightMessages = options->maxInflight; diff --git a/src/MQTTAsyncUtils.c b/src/MQTTAsyncUtils.c index 29117fcc..6605014d 100644 --- a/src/MQTTAsyncUtils.c +++ b/src/MQTTAsyncUtils.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2023 IBM Corp., Ian Craggs and others + * 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 @@ -1998,6 +1998,26 @@ static int MQTTAsync_completeConnection(MQTTAsyncs* m, Connack* connack) if (m->c->connected != 1) rc = MQTTASYNC_DISCONNECTED; } + if (m->c->MQTTVersion == MQTTVERSION_5) + { + if (MQTTProperties_hasProperty(&connack->properties, MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE)) + { + /* update the keep alive from the server keep alive */ + int server_keep_alive = MQTTProperties_getNumericValue(&connack->properties, MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE); + if (server_keep_alive != -999999) + { + Log(LOG_PROTOCOL, -1, "Setting keep alive interval to server keep alive %d", server_keep_alive); + m->c->keepAliveInterval = server_keep_alive; + } + } + else if (m->c->keepAliveInterval != m->c->savedKeepAliveInterval) + { + /* if the keep alive has been previously updated with a server keep alive, but there is no server keep alive + on this connect, reset it to the value requested in the original connect API */ + Log(LOG_PROTOCOL, -1, "Resetting keep alive interval to %d", m->c->savedKeepAliveInterval); + m->c->keepAliveInterval = m->c->savedKeepAliveInterval; + } + } } m->pack = NULL; #if !defined(_WIN32) && !defined(_WIN64) diff --git a/src/MQTTClient.c b/src/MQTTClient.c index b6a7714b..b80b0c08 100644 --- a/src/MQTTClient.c +++ b/src/MQTTClient.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2009, 2023 IBM Corp., Ian Craggs and others + * 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 @@ -1428,7 +1428,7 @@ static MQTTResponse MQTTClient_connectURIVersion(MQTTClient handle, MQTTClient_c m->c->connected = 1; m->c->good = 1; m->c->connect_state = NOT_IN_PROGRESS; - if (MQTTVersion == 4) + if (MQTTVersion >= MQTTVERSION_3_1_1) sessionPresent = connack->flags.bits.sessionPresent; if (m->c->cleansession || m->c->cleanstart) rc = MQTTClient_cleanSession(m->c); @@ -1454,6 +1454,24 @@ static MQTTResponse MQTTClient_connectURIVersion(MQTTClient handle, MQTTClient_c goto exit; } *resp.properties = MQTTProperties_copy(&connack->properties); + + if (MQTTProperties_hasProperty(&connack->properties, MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE)) + { + /* update the keep alive from the server keep alive */ + int server_keep_alive = MQTTProperties_getNumericValue(&connack->properties, MQTTPROPERTY_CODE_SERVER_KEEP_ALIVE); + if (server_keep_alive != -999999) + { + Log(LOG_PROTOCOL, -1, "Setting keep alive interval to server keep alive %d", server_keep_alive); + m->c->keepAliveInterval = server_keep_alive; + } + } + else if (m->c->keepAliveInterval != m->c->savedKeepAliveInterval) + { + /* if the keep alive has been previously updated with a server keep alive, but there is no server keep alive + on this connect, reset it to the value requested in the original connect API */ + Log(LOG_PROTOCOL, -1, "Resetting keep alive interval to %d", m->c->savedKeepAliveInterval); + m->c->keepAliveInterval = m->c->savedKeepAliveInterval; + } } } MQTTPacket_freeConnack(connack); @@ -1507,7 +1525,7 @@ static MQTTResponse MQTTClient_connectURI(MQTTClient handle, MQTTClient_connectO start = MQTTTime_start_clock(); m->currentServerURI = serverURI; - m->c->keepAliveInterval = options->keepAliveInterval; + m->c->keepAliveInterval = m->c->savedKeepAliveInterval = options->keepAliveInterval; m->c->retryInterval = options->retryInterval; setRetryLoopInterval(options->keepAliveInterval); m->c->MQTTVersion = options->MQTTVersion;