From c388b3cb10ce98bd7f6d16891f4a4d4d53cd7200 Mon Sep 17 00:00:00 2001
From: David Girault <dgirault@sevenhugs.com>
Date: Tue, 15 Oct 2019 14:47:14 +0200
Subject: [PATCH 4/4] mqtt: add persistent session support

On connect, application can provide flags to start with a clean session.

On CONNACK reception, forward the acknowledge information to application.

Application can manage its subscribtion according of the received session persistent flag.
---
 src/apps/mqtt/mqtt.c         | 14 ++++++++------
 src/include/lwip/apps/mqtt.h | 16 +++++++++++++++-
 2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/src/apps/mqtt/mqtt.c b/src/apps/mqtt/mqtt.c
index 5aea78db..8add18bb 100644
--- a/src/apps/mqtt/mqtt.c
+++ b/src/apps/mqtt/mqtt.c
@@ -562,7 +562,7 @@ mqtt_close(mqtt_client_t *client, mqtt_connection_status_t reason)
 
     client->conn_state = TCP_DISCONNECTED;
     if (client->connect_cb != NULL) {
-      client->connect_cb(client, client->connect_arg, reason);
+      client->connect_cb(client, client->connect_arg, reason, 0);
     }
   }
 }
@@ -672,7 +672,7 @@ mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_len, u16_t length, u
                       u8_t *var_hdr_payload)
 {
   mqtt_connection_status_t res = MQTT_CONNECT_ACCEPTED;
-
+  u8_t ack_flags = 0;
   /* Control packet type */
   u8_t pkt_type = MQTT_CTL_PACKET_TYPE(client->rx_buffer[0]);
   u16_t pkt_id = 0;
@@ -687,6 +687,8 @@ mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_len, u16_t length, u
         LWIP_DEBUGF(MQTT_DEBUG_WARN,( "mqtt_message_received: Received short CONNACK message\n"));
         goto out_disconnect;
       }
+      /* Get acknowledge flags from CONNACK */
+      ack_flags = var_hdr_payload[0];
       /* Get result code from CONNACK */
       res = (mqtt_connection_status_t)var_hdr_payload[1];
       LWIP_DEBUGF(MQTT_DEBUG_TRACE, ("mqtt_message_received: Connect response code %d\n", res));
@@ -696,7 +698,7 @@ mqtt_message_received(mqtt_client_t *client, u8_t fixed_hdr_len, u16_t length, u
         client->conn_state = MQTT_CONNECTED;
         /* Notify upper layer */
         if (client->connect_cb != 0) {
-          client->connect_cb(client, client->connect_arg, res);
+          client->connect_cb(client, client->connect_arg, res, ack_flags);
         }
       }
     } else {
@@ -1359,9 +1361,9 @@ mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port,
     LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);
     remaining_length = (u16_t)len;
   }
-
-  /* Don't complicate things, always connect using clean session */
-  flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
+  if ((client_info->flags & MQTT_CONNECT_CLIENT_FLAGS_CLEAN_SESSION) != 0) {
+    flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;
+  }
 
   len = strlen(client_info->client_id);
   LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL);
diff --git a/src/include/lwip/apps/mqtt.h b/src/include/lwip/apps/mqtt.h
index 22e4002f..1d86c001 100644
--- a/src/include/lwip/apps/mqtt.h
+++ b/src/include/lwip/apps/mqtt.h
@@ -62,6 +62,11 @@ typedef struct mqtt_client_s mqtt_client_t;
 /*---------------------------------------------------------------------------------------------- */
 /* Connection with server */
 
+/**
+ * @ingroup mqtt
+ * Use clean session */
+#define MQTT_CONNECT_CLIENT_FLAGS_CLEAN_SESSION    (1 << 0)
+
 /**
  * @ingroup mqtt
  * Client information and connection parameters */
@@ -83,6 +88,8 @@ struct mqtt_connect_client_info_t {
   u8_t will_qos;
   /** will_retain, see will_topic */
   u8_t will_retain;
+  /** Connection flags */
+  u8_t flags;
 #if LWIP_ALTCP && LWIP_ALTCP_TLS
   /** TLS configuration for secure connections */
   struct altcp_tls_config *tls_config;
@@ -114,6 +121,11 @@ typedef enum
   MQTT_CONNECT_TIMEOUT                  = 257
 } mqtt_connection_status_t;
 
+/**
+ * @ingroup mqtt
+ * Session present acknowledge connection flag */
+#define MQTT_CONNECT_ACK_FLAGS_SESSION_PRESENT    (1 << 0)
+
 /**
  * @ingroup mqtt
  * Function prototype for mqtt connection status callback. Called when
@@ -123,9 +135,11 @@ typedef enum
  * @param client MQTT client itself
  * @param arg Additional argument to pass to the callback function
  * @param status Connect result code or disconnection notification @see mqtt_connection_status_t
+ * @param ack_flags Acknowledge connection flags from CONNACK
  *
  */
-typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg, mqtt_connection_status_t status);
+typedef void (*mqtt_connection_cb_t)(mqtt_client_t *client, void *arg,
+              mqtt_connection_status_t status, u8_t ack_flags);
 
 
 /**
-- 
2.20.1

