From 880698e71b17aeb8368544082fea74cfc5be04c7 Mon Sep 17 00:00:00 2001
From: guowenxue <guowenxue@gmail.com>
Date: Sat, 15 Nov 2025 00:32:20 +0800
Subject: [PATCH] update Raspberry Pi project
---
project/booster/test/comport.c | 263 +++++++++++++++++++++++++++++++++++++++++++
utils/pwm.c | 0
.gitignore | 19 ++
project/openlibs/libevent/build.sh | 2
project/openlibs/openssl/build.sh | 2
utils/sht20.c | 0
project/openlibs/libgpiod/build.sh | 2
utils/relay.c | 0
utils/makefile | 0
project/openlibs/cjson/build.sh | 2
project/openlibs/mosquitto/build.sh | 2
utils/leds.c | 0
utils/at24c.c | 0
project/booster/util_proc.c | 4
utils/diagram/AT24C256.kvdat | 0
project/openlibs/makefile | 8 +
utils/tsl2561.c | 0
utils/ds18b20.c | 0
project/booster/makefile | 3
/dev/null | 7 -
utils/diagram/SHT20.kvdat | 0
utils/infrared.c | 0
utils/w25qflash.h | 0
project/booster/test/makefile | 14 -
utils/w25qflash.c | 0
25 files changed, 298 insertions(+), 30 deletions(-)
diff --git a/.gitignore b/.gitignore
index 629aa34..ee9b810 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,11 +4,24 @@
install/
# ignore files
-*.so*
+*.tar*
*.o
-*.a
+lib*.so*
+lib*.a
+mqttd
+
+# ctags files
cscope.*
tags
-*.tar*
+
+# running files
*.log
*.db
+
+# openlibs
+cJSON-*
+mosquitto-*
+libgpiod-*
+openssl-*
+sqlite-*
+libevent-*
diff --git a/project/booster/makefile b/project/booster/makefile
index 0fd869e..3525db8 100644
--- a/project/booster/makefile
+++ b/project/booster/makefile
@@ -11,7 +11,7 @@
#
#*******************************************************************************
-PWD=$(shell pwd )
+PWD=$(shell pwd)
BUILD_ARCH=$(shell uname -m)
ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
@@ -22,7 +22,6 @@
LIBNAME=$(shell basename ${PWD} )
TOPDIR=$(shell dirname ${PWD} )
-CFLAGS+=-D_GNU_SOURCE
all: clean
@rm -f *.o
diff --git a/project/booster/test/comport.c b/project/booster/test/comport.c
new file mode 100644
index 0000000..d15b491
--- /dev/null
+++ b/project/booster/test/comport.c
@@ -0,0 +1,263 @@
+/*********************************************************************************
+ * Copyright: (C) 2012 Guo Wenxue <guowenxue@gmail.com>
+ * All rights reserved.
+ *
+ * Filename: comport.c
+ * Description: This file used to do ioctl() on common device or communicate
+ * with serial port/TTY device.
+ *
+ * Version: 1.0.0(10/18/2011~)
+ * Author: Guo Wenxue <guowenxue@gmail.com>
+ * ChangeLog: 1, Release initial version on "10/18/2011 10:08:05 AM"
+ *
+ ********************************************************************************/
+#include <getopt.h>
+#include <libgen.h>
+#include <sys/ioctl.h>
+
+#include "comport.h"
+
+unsigned char g_ucProcToken = 0x01;
+unsigned char g_ucCtrlZ;
+
+void print_version(char *name);
+void usage(char *name);
+int do_ioctl(char *dev_name, int cmd, int arg);
+void signal_handler(int i_sig);
+void nonblock(void);
+int kbhit(void);
+
+int main(int argc, char **argv)
+{
+ int opt = 0;
+ int retval = 0;
+ int recv_size = 0;
+ int i;
+ char *dev_name = NULL;
+ int baudrate = 115200;
+ char *settings = "8N1N";
+ char buf[512];
+ unsigned char disp_mode = 0x00;
+ comport_t comport;
+
+ struct sigaction sigact;
+
+ struct option long_options[] = {
+ {"device", required_argument, NULL, 'd'},
+ {"baudrate", required_argument, NULL, 'b'},
+ {"settings", required_argument, NULL, 's'},
+ {"ioctl", required_argument, NULL, 'i'},
+ {"hex", no_argument, NULL, 'x'},
+ {"version", no_argument, NULL, 'v'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((opt = getopt_long(argc, argv, "d:b:s:ivh", long_options, NULL)) != -1)
+ {
+ switch (opt)
+ {
+ case 'd':
+ dev_name = optarg;
+ break;
+ case 'b':
+ baudrate = atoi(optarg);
+ break;
+ case 's': /* Default settings as 8N1N */
+ settings = optarg;
+ break;
+ case 'i':
+ if (5 != argc)
+ {
+ usage(argv[0]);
+ }
+ else
+ {
+ do_ioctl(argv[2], atoi(argv[3]), atoi(argv[4]));
+ }
+ return 0;
+ case 'x': /* Display receive data as Hex mode */
+ disp_mode = 0x01;
+ break;
+ case 'v': /* version */
+ print_version(argv[0]);
+ return 0;
+ case 'h': /* help */
+ usage(argv[0]);
+ return 0;
+ default:
+ break;
+ } /* end of "switch(opt)" */
+ }
+
+ if (argc < 2)
+ {
+ usage(argv[0]);
+ return 0;
+ }
+
+ if( comport_open(&comport, dev_name, baudrate, settings) < 0 )
+ {
+ printf("Failed to open %s with baudrate %d, %s. RetCode [%d]\n", dev_name, baudrate,
+ settings, retval);
+ return -1;
+ }
+
+ nonblock();
+
+ /* Process level signal handler */
+ sigemptyset(&sigact.sa_mask);
+ sigact.sa_flags = 0;
+ sigact.sa_handler = signal_handler;
+
+ sigaction(SIGTERM, &sigact, NULL); /* catch terminate signal */
+ sigaction(SIGINT, &sigact, NULL); /* catch interrupt signal */
+ sigaction(SIGSEGV, &sigact, NULL); /* catch segmentation faults */
+ sigaction(SIGTSTP, &sigact, NULL); /* catch ctrl+Z */
+ sigaction(SIGSTOP, &sigact, NULL); /* catch ctrl+Z */
+
+ while (0x01 == g_ucProcToken)
+ {
+ recv_size = comport_recv(&comport, buf, sizeof(buf) - 1, 10);
+ if (recv_size > 0)
+ {
+ for (i = 0; i < recv_size; i++)
+ {
+ if (0 == disp_mode)
+ printf("%c", buf[i]);
+ else
+ printf("%02X ", buf[i]);
+ }
+ fflush(stdout);
+ }
+ if (0 != kbhit())
+ {
+ retval = fgetc(stdin);
+
+ if (0x0A == retval)
+ {
+ buf[0] = 0x0D; /* 13 == 0x0D */
+ }
+ else
+ {
+ buf[0] = retval;
+ }
+
+ comport_send(&comport, buf, 1);
+ }
+ else if (0x00 != g_ucCtrlZ)
+ {
+ g_ucCtrlZ = 0x00;
+ buf[0] = 0x1A;
+ comport_send(&comport, buf, 1);
+ }
+ }
+
+ comport_close(&comport);
+ return 0;
+}
+
+void print_version(char *name)
+{
+ char *progname = NULL;
+ char *ptr = NULL;
+
+ ptr = strdup(name);
+ progname = basename(ptr);
+
+ printf("%s version: 1.0.0 on %s\n", progname, __DATE__);
+ printf("Copyright (C) 2010 guowenxue <guowenxue@gmail.com>\n");
+
+ free(ptr);
+ return;
+}
+
+void usage(char *name)
+{
+ char *progname = NULL;
+ char *ptr = NULL;
+
+ ptr = strdup(name);
+ progname = basename(ptr);
+ printf("Usage1: comport -d <device> [-b <baudrate>][-s <settings>] [-x]\n");
+ printf("Usage2: comport [-i <driver port> <cmd> <arg>][--help][--version]\n");
+ printf(" -d[device ] device name\n");
+ printf(" -b[baudrate] device baudrate (115200, 57600, 19200, 9600), default is 115200\n");
+ printf(" -s[settings] device settings as like 8N1N(default setting)\n");
+ printf(" - data bits: 8, 7\n");
+ printf(" - parity: N=None, O=Odd, E=Even, S=Space\n");
+ printf(" - stop bits: 1, 0\n");
+ printf(" - flow control: N=None, H=Hardware, S=Software, B=Both\n");
+ printf(" -x[hex ] display received data in hex format\n");
+ printf(" -i[ioctl ] ioctl system call (cmd & arg only support int)\n");
+ printf(" -v[version ] Display the program version\n");
+ printf(" -h[help ] Display this help information\n");
+
+ print_version(progname);
+
+ free(ptr);
+
+ return;
+}
+
+int do_ioctl(char *dev_name, int cmd, int arg)
+{
+ int fd = -1;
+ int retval = -1;
+ if (((fd = open(dev_name, O_RDWR)) < 0))
+ {
+ printf("Open device \"%s\" failure: %s\n", dev_name, strerror(errno));
+ return -1;
+ }
+
+ retval = ioctl(fd, cmd, arg);
+ printf("ioctl (%s, %d, %d) returned %d\n", dev_name, cmd, arg, retval);
+
+ close(fd);
+ return retval;
+}
+
+void signal_handler(int i_sig)
+{
+ if (SIGTERM == i_sig || SIGINT == i_sig)
+ {
+ g_ucProcToken = 0x00;
+ }
+ else if (20 == i_sig)
+ {
+ g_ucCtrlZ = 0x01;
+ }
+}
+
+void nonblock(void)
+{
+ struct termios ttystate;
+
+ //get the terminal state
+ tcgetattr(STDIN_FILENO, &ttystate);
+
+ //turn off canonical mode
+ ttystate.c_lflag &= ~ICANON;
+
+ //minimum of number input read.
+ ttystate.c_cc[VMIN] = 1;
+
+ //set the terminal attributes.
+ tcsetattr(STDIN_FILENO, TCSANOW, &ttystate);
+}
+
+
+int kbhit(void)
+{
+ struct timeval tv;
+
+ fd_set fds;
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+ FD_ZERO(&fds);
+ FD_SET(STDIN_FILENO, &fds); //STDIN_FILENO is 0
+
+ select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
+
+ return FD_ISSET(STDIN_FILENO, &fds);
+}
diff --git a/project/booster/test/makefile b/project/booster/test/makefile
index 45b59cc..58d311a 100644
--- a/project/booster/test/makefile
+++ b/project/booster/test/makefile
@@ -15,19 +15,13 @@
PWD=$(shell pwd)
LIB_PATH=$(shell dirname ${PWD})
LIB_NAME=$(shell basename ${LIB_PATH})
-INSTPATH=/tftp
-
-#ARCH ?= i386
-#ARCH?=arm926t
-ARCH?=arm920t
-
-#LINK_MODE=STATIC
-MODE=PRODUCTION
-DEBUG=1
INSTPATH=/tftp
-#CROSS_COMPILE=aarch64-linux-gnu-
+BUILD_ARCH=$(shell uname -m)
+ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
+ CROSS_COMPILE?=arm-linux-gnueabihf-
+endif
export CC=${CROSS_COMPILE}gcc
export CXX=${CROSS_COMPILE}g++
diff --git a/project/booster/util_proc.c b/project/booster/util_proc.c
index dfdabae..1a3d127 100644
--- a/project/booster/util_proc.c
+++ b/project/booster/util_proc.c
@@ -161,7 +161,7 @@
if( check_daemon_running(pidfile) )
{
- log_error("Program already running, process exit now");
+ log_error("Program already running, process exit now\n");
return -1;
}
@@ -357,7 +357,7 @@
* *****************************************************************************/
int set_daemon_running(const char *pid_file)
{
- daemonize(0, 1);
+ daemon(0, 1);
log_info("Program running as daemon [PID:%d].\n", getpid());
if (record_daemon_pid(pid_file) < 0)
diff --git a/project/coreMQTT/conf.c b/project/coreMQTT/conf.c
deleted file mode 100644
index 4c0ee20..0000000
--- a/project/coreMQTT/conf.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2019 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: conf.c
- * Description: This file is mqttd configure file parser function
- *
- * Version: 1.0.0(2019年06月25日)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2019年06月25日 22时23分55秒"
- *
- ********************************************************************************/
-#include "conf.h"
-#include "logger.h"
-#include "iniparser.h"
-
-
-int mqttd_parser_conf(const char *conf_file, mqtt_ctx_t *ctx, int debug)
-{
- dictionary *ini;
- const char *str;
- int val;
- int rv = 0;
-
- if( !conf_file || !ctx )
- {
- fprintf(stderr, "%s() Invalid input arguments\n", __func__);
- return -1;
- }
-
- memset(ctx, 0, sizeof(*ctx));
-
- ini = iniparser_load(conf_file);
- if( !ini )
- {
- fprintf(stderr, "ERROR: Configure file '%s' load failed\n", conf_file);
- return -2;
- }
-
- /*+------------------------------------------------------+
- *| parser logger settings and start logger system |
- *+------------------------------------------------------+*/
- if( !debug )
- {
- str = iniparser_getstring(ini, "logger:file", "/tmp/mqttd.log");
- strncpy(ctx->logfile, str, sizeof(ctx->logfile));
- ctx->logsize = iniparser_getint(ini, "logger:size", 1024);
- ctx->loglevel = iniparser_getint(ini, "logger:level", LOG_LEVEL_INFO);
- }
- else
- {
- strncpy(ctx->logfile, "console", sizeof(ctx->logfile));
- ctx->loglevel = LOG_LEVEL_DEBUG;
- ctx->logsize = 0;
- }
-
- if( log_open(ctx->logfile, ctx->loglevel, ctx->logsize, LOG_LOCK_DISABLE) < 0 )
- {
- fprintf(stderr, "Logger system initialise failure\n");
- return -2;
- }
-
- log_info("Logger system initialise ok\n");
-
-
- /*+------------------------------------------------------+
- *| parser production ID |
- *+------------------------------------------------------+*/
-
- if( !(str=iniparser_getstring(ini, "common:devid", NULL)) )
- {
- log_error("ERROR: Parser device ID failure\n");
- rv = -3;
- goto cleanup;
- }
- /* cJSON parser ID will get "" */
- snprintf(ctx->devid, sizeof(ctx->devid), "\"%s\"", str);
- log_info("Parser device ID [%s]\n", ctx->devid);
-
-
- /*+------------------------------------------------------+
- *| parser hardware module configuration |
- *+------------------------------------------------------+*/
-
- /* relay */
- ctx->hwconf.relay=iniparser_getint(ini, "hardware:relay", 0);
- if( !ctx->hwconf.relay )
- log_warn("Parser relay module disabled\n");
- else
- log_info("Parser relay module enabled\n");
-
- /* RGB 3-colors LED */
- ctx->hwconf.led=iniparser_getint(ini, "hardware:rgbled", 0);
- if( !ctx->hwconf.led )
- log_warn("Parser RGB 3-colors Led module disabled\n");
- else
- log_info("Parser RGB 3-colors Led module enabled\n");
-
- /* beeper */
- ctx->hwconf.beeper=iniparser_getint(ini, "hardware:beep", 0);
- if( !ctx->hwconf.beeper )
- log_warn("Parser beeper module disabled\n");
- else
- log_info("Parser beeper module enabled\n");
-
- /* DS18B20 temperature module */
- ctx->hwconf.ds18b20=iniparser_getint(ini, "hardware:ds18b20", 0);
- if( !ctx->hwconf.ds18b20 )
- log_warn("Parser DS18B20 temperature module disabled\n");
- else
- log_info("Parser DS18B20 temperature module enabled\n");
-
- /* SHT20 temperature and hummidity module */
- ctx->hwconf.sht2x=iniparser_getint(ini, "hardware:sht2x", 0);
- if( !ctx->hwconf.sht2x )
- log_warn("Parser SHT2X temperature and hummidity module disabled\n");
- else
- log_info("Parser SHT2X temperature and hummidity module enabled\n");
-
- /* TSL2561 light intensity sensor module */
- ctx->hwconf.tsl2561=iniparser_getint(ini, "hardware:tsl2561", 0);
- if( !ctx->hwconf.tsl2561 )
- log_warn("Parser TSL2561 light intensity sensor module disabled\n");
- else
- log_info("Parser TSL2561 light intensity sensor module enabled\n");
-
- /*+------------------------------------------------------+
- *| parser broker settings |
- *+------------------------------------------------------+*/
-
- if( !(str=iniparser_getstring(ini, "broker:hostname", NULL)) )
- {
- log_error("ERROR: Parser MQTT broker server hostname failure\n");
- rv = -4;
- goto cleanup;
- }
- strncpy(ctx->host, str, sizeof(ctx->host) );
-
- if( (val=iniparser_getint(ini, "broker:port", -1)) < 0 )
- {
- log_error("ERROR: Parser MQTT broker server port failure\n");
- rv = -5;
- goto cleanup;
- }
- ctx->port = val;
- log_info("Parser MQTT broker server [%s:%d]\n", ctx->host, ctx->port);
-
- str=iniparser_getstring(ini, "broker:username", NULL);
- strncpy(ctx->uid, str, sizeof(ctx->uid) );
-
- str=iniparser_getstring(ini, "broker:password", NULL);
- strncpy(ctx->pwd, str, sizeof(ctx->pwd) );
-
- if( ctx->uid && ctx->pwd )
- log_info("Parser broker author by [%s:%s]\n", ctx->uid, ctx->pwd);
-
- ctx->keepalive = iniparser_getint(ini, "broker:keepalive", DEF_KEEPALIVE);
- log_info("Parser broker keepalive timeout [%d] seconds\n", ctx->keepalive);
-
- /*+------------------------------------------------------+
- *| parser publisher settings |
- *+------------------------------------------------------+*/
-
- if( !(str=iniparser_getstring(ini, "publisher:pubTopic", NULL)) )
- {
- log_error("ERROR: Parser MQTT broker publisher topic failure\n");
- rv = -6;
- goto cleanup;
- }
- strncpy(ctx->pubTopic, str, sizeof(ctx->pubTopic) );
-
- ctx->pubQos = iniparser_getint(ini, "publisher:pubQos", DEF_QOS);
- ctx->interval = iniparser_getint(ini, "publisher:interval", DEF_PUBINTERVAL);
- log_info("Parser publisher topic \"%s\" with Qos[%d] interval[%d]\n", ctx->pubTopic, ctx->pubQos, ctx->interval);
-
- /*+------------------------------------------------------+
- *| parser subscriber settings |
- *+------------------------------------------------------+*/
-
- if( !(str=iniparser_getstring(ini, "subsciber:subTopic", NULL)) )
- {
- log_error("ERROR: Parser MQTT broker publisher topic failure\n");
- rv = -7;
- goto cleanup;
- }
- strncpy(ctx->subTopic, str, sizeof(ctx->subTopic) );
-
- ctx->subQos = iniparser_getint(ini, "subsciber:subQos", DEF_QOS);
- log_info("Parser subscriber topic \"%s\" with Qos[%d]\n", ctx->subTopic, ctx->subQos);
-
-cleanup:
- if( ini )
- iniparser_freedict(ini);
-
- if( rv )
- log_close();
-
- return rv;
-}
-
diff --git a/project/coreMQTT/conf.h b/project/coreMQTT/conf.h
deleted file mode 100644
index 89d3a66..0000000
--- a/project/coreMQTT/conf.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2019 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: conf.h
- * Description: This file is mqttd configure file parser function
- *
- * Version: 1.0.0(2019年06月25日)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2019年06月25日 22时23分55秒"
- *
- ********************************************************************************/
-#ifndef __CONF_H_
-#define __CONF_H_
-
-enum
-{
- Qos0, /* 发送者只发送一次消息,不进行重试,Broker不会返回确认消息。在Qos0情况下,Broker可能没有接受到消息 */
- Qos1, /* 发送者最少发送一次消息,确保消息到达Broker,Broker需要返回确认消息PUBACK。在Qos1情况下,Broker可能接受到重复消息 */
- Qos2, /* Qos2使用两阶段确认来保证消息的不丢失和不重复。在Qos2情况下,Broker肯定会收到消息,且只收到一次 */
-};
-
-#define DEF_KEEPALIVE 30
-#define DEF_PUBINTERVAL 120
-#define DEF_QOS Qos2
-
-typedef struct hwconf_s
-{
- int relay; /* relay aviable or not. 0:Disable 1: Enable */
- int led; /* RGB led aviable or not. 0:Disable 1: Enable */
- int beeper; /* beeper aviable or not. 0:Disable 1: Enable */
- int ds18b20; /* DS1B820 aviable or not. 0:Disable 1: Enable */
- int sht2x; /* SHT20 aviable or not. 0:Disable 1: Enable */
- int tsl2561; /* TSL2561 aviable or not. 0:Disable 1: Enable */
-} hwconf_t;
-
-
-typedef struct mqtt_ctx_s
-{
- char devid[32]; /* device ID */
-
- /* hardware configuration */
- hwconf_t hwconf;
-
- /* logger settings */
- char logfile[128]; /* logger record file */
- int loglevel; /* logger level */
- int logsize; /* logger file maxsize, oversize will rollback */
-
- /* Broker settings */
- char host[128]; /* MQTT broker server name */
- int port; /* MQTT broker listen port */
- char uid[64]; /* username */
- char pwd[64]; /* password */
- int keepalive; /* MQTT broker send PING message to subsciber/publisher keepalive timeout<seconds> */
-
- /* Publisher settings */
- char pubTopic[256]; /* Publisher topic */
- int pubQos; /* Publisher Qos */
- int interval ; /* Publish sensor data interval time, unit seconds */
-
- /* Subscriber settings */
- char subTopic[256]; /* Subscriber topic */
- int subQos; /* Subscriber Qos */
-} mqtt_ctx_t;
-
-
-extern int mqttd_parser_conf(const char *conf_file, mqtt_ctx_t *ctx, int debug);
-
-#endif /* ----- #ifndef _CONF_H_ ----- */
-
diff --git a/project/coreMQTT/coreJSON/README.md b/project/coreMQTT/coreJSON/README.md
deleted file mode 100644
index d08f61f..0000000
--- a/project/coreMQTT/coreJSON/README.md
+++ /dev/null
@@ -1,65 +0,0 @@
-## coreJSON Library
-
-This repository contains the coreJSON library, a parser that strictly enforces the ECMA-404 JSON standard and is suitable for low memory footprint embedded devices. The coreJSON library is distributed under the [MIT Open Source License](LICENSE).
-
-This library has gone through code quality checks including verification that no function has a [GNU Complexity](https://www.gnu.org/software/complexity/manual/complexity.html) score over 8, and checks against deviations from mandatory rules in the [MISRA coding standard](https://www.misra.org.uk). Deviations from the MISRA C:2012 guidelines are documented under [MISRA Deviations](MISRA.md). This library has also undergone both static code analysis from [Coverity static analysis](https://scan.coverity.com/), and validation of memory safety through the [CBMC automated reasoning tool](https://www.cprover.org/cbmc/).
-
-See memory requirements for this library [here](./docs/doxygen/include/size_table.md).
-
-**coreJSON v3.2.0 [source code](https://github.com/FreeRTOS/coreJSON/tree/v3.2.0/source) is part of the [FreeRTOS 202210.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202210.00-LTS) release.**
-
-**coreJSON v3.0.0 [source code](https://github.com/FreeRTOS/coreJSON/tree/v3.0.0/source) is part of the [FreeRTOS 202012.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202012.00-LTS) release.**
-
-## Reference example
-
-```c
-#include <stdio.h>
-#include "core_json.h"
-
-int main()
-{
- // Variables used in this example.
- JSONStatus_t result;
- char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}";
- size_t bufferLength = sizeof( buffer ) - 1;
- char queryKey[] = "bar.foo";
- size_t queryKeyLength = sizeof( queryKey ) - 1;
- char * value;
- size_t valueLength;
-
- // Calling JSON_Validate() is not necessary if the document is guaranteed to be valid.
- result = JSON_Validate( buffer, bufferLength );
-
- if( result == JSONSuccess )
- {
- result = JSON_Search( buffer, bufferLength, queryKey, queryKeyLength,
- &value, &valueLength );
- }
-
- if( result == JSONSuccess )
- {
- // The pointer "value" will point to a location in the "buffer".
- char save = value[ valueLength ];
- // After saving the character, set it to a null byte for printing.
- value[ valueLength ] = '\0';
- // "Found: bar.foo -> xyz" will be printed.
- printf( "Found: %s -> %s\n", queryKey, value );
- // Restore the original character.
- value[ valueLength ] = save;
- }
-
- return 0;
-}
-```
-A search may descend through nested objects when the `queryKey` contains matching key strings joined by a separator, `.`. In the example above, `bar` has the value `{"foo":"xyz"}`. Therefore, a search for query key `bar.foo` would output `xyz`.
-
-## Documentation
-
-For pre-generated documentation, please see the documentation linked in the locations below:
-
-| Location |
-| :-: |
-| [FreeRTOS.org](https://freertos.org/Documentation/api-ref/coreJSON/docs/doxygen/output/html/index.html) |
-
-Note that the latest included version of the coreJSON library may differ across repositories.
-
diff --git a/project/coreMQTT/coreJSON/core_json.c b/project/coreMQTT/coreJSON/core_json.c
deleted file mode 100644
index 06a0cb4..0000000
--- a/project/coreMQTT/coreJSON/core_json.c
+++ /dev/null
@@ -1,1818 +0,0 @@
-/*
- * coreJSON v3.2.0
- * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_json.c
- * @brief The source file that implements the user-facing functions in core_json.h.
- */
-
-#include <assert.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-#include "core_json.h"
-
-/** @cond DO_NOT_DOCUMENT */
-
-/* A compromise to satisfy both MISRA and CBMC */
-typedef union
-{
- char c;
- uint8_t u;
-} char_;
-
-#if ( CHAR_MIN == 0 )
- #define isascii_( x ) ( ( x ) <= '\x7F' )
-#else
- #define isascii_( x ) ( ( x ) >= '\0' )
-#endif
-#define iscntrl_( x ) ( isascii_( x ) && ( ( x ) < ' ' ) )
-#define isdigit_( x ) ( ( ( x ) >= '0' ) && ( ( x ) <= '9' ) )
-/* NB. This is whitespace as defined by the JSON standard (ECMA-404). */
-#define isspace_( x ) \
- ( ( ( x ) == ' ' ) || ( ( x ) == '\t' ) || \
- ( ( x ) == '\n' ) || ( ( x ) == '\r' ) )
-
-#define isOpenBracket_( x ) ( ( ( x ) == '{' ) || ( ( x ) == '[' ) )
-#define isCloseBracket_( x ) ( ( ( x ) == '}' ) || ( ( x ) == ']' ) )
-#define isCurlyPair_( x, y ) ( ( ( x ) == '{' ) && ( ( y ) == '}' ) )
-#define isSquarePair_( x, y ) ( ( ( x ) == '[' ) && ( ( y ) == ']' ) )
-#define isMatchingBracket_( x, y ) ( isCurlyPair_( x, y ) || isSquarePair_( x, y ) )
-#define isSquareOpen_( x ) ( ( x ) == '[' )
-#define isSquareClose_( x ) ( ( x ) == ']' )
-
-/**
- * @brief Advance buffer index beyond whitespace.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- */
-static void skipSpace( const char * buf,
- size_t * start,
- size_t max )
-{
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- for( i = *start; i < max; i++ )
- {
- if( !isspace_( buf[ i ] ) )
- {
- break;
- }
- }
-
- *start = i;
-}
-
-/**
- * @brief Count the leading 1s in a byte.
- *
- * The high-order 1 bits of the first byte in a UTF-8 encoding
- * indicate the number of additional bytes to follow.
- *
- * @return the count
- */
-static size_t countHighBits( uint8_t c )
-{
- uint8_t n = c;
- size_t i = 0;
-
- while( ( n & 0x80U ) != 0U )
- {
- i++;
- n = ( n & 0x7FU ) << 1U;
- }
-
- return i;
-}
-
-/**
- * @brief Is the value a legal Unicode code point and encoded with
- * the fewest bytes?
- *
- * The last Unicode code point is 0x10FFFF.
- *
- * Unicode 3.1 disallows UTF-8 interpretation of non-shortest form sequences.
- * 1 byte encodes 0 through 7 bits
- * 2 bytes encode 8 through 5+6 = 11 bits
- * 3 bytes encode 12 through 4+6+6 = 16 bits
- * 4 bytes encode 17 through 3+6+6+6 = 21 bits
- *
- * Unicode 3.2 disallows UTF-8 code point values in the surrogate range,
- * [U+D800 to U+DFFF].
- *
- * @note Disallow ASCII, as this is called only for multibyte sequences.
- */
-static bool shortestUTF8( size_t length,
- uint32_t value )
-{
- bool ret = false;
- uint32_t min, max;
-
- assert( ( length >= 2U ) && ( length <= 4U ) );
-
- switch( length )
- {
- case 2:
- min = ( uint32_t ) 1 << 7U;
- max = ( ( uint32_t ) 1 << 11U ) - 1U;
- break;
-
- case 3:
- min = ( uint32_t ) 1 << 11U;
- max = ( ( uint32_t ) 1 << 16U ) - 1U;
- break;
-
- default:
- min = ( uint32_t ) 1 << 16U;
- max = 0x10FFFFU;
- break;
- }
-
- if( ( value >= min ) && ( value <= max ) &&
- ( ( value < 0xD800U ) || ( value > 0xDFFFU ) ) )
- {
- ret = true;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond a UTF-8 code point.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a valid code point was present;
- * false otherwise.
- *
- * 00-7F Single-byte character
- * 80-BF Trailing byte
- * C0-DF Leading byte of two-byte character
- * E0-EF Leading byte of three-byte character
- * F0-F7 Leading byte of four-byte character
- * F8-FB Illegal (formerly leading byte of five-byte character)
- * FC-FD Illegal (formerly leading byte of six-byte character)
- * FE-FF Illegal
- *
- * The octet values C0, C1, and F5 to FF are illegal, since C0 and C1
- * would introduce a non-shortest sequence, and F5 or above would
- * introduce a value greater than the last code point, 0x10FFFF.
- */
-static bool skipUTF8MultiByte( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
- size_t i, bitCount, j;
- uint32_t value = 0;
- char_ c;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
- assert( i < max );
- assert( !isascii_( buf[ i ] ) );
-
- c.c = buf[ i ];
-
- if( ( c.u > 0xC1U ) && ( c.u < 0xF5U ) )
- {
- bitCount = countHighBits( c.u );
- value = ( ( uint32_t ) c.u ) & ( ( ( uint32_t ) 1 << ( 7U - bitCount ) ) - 1U );
-
- /* The bit count is 1 greater than the number of bytes,
- * e.g., when j is 2, we skip one more byte. */
- for( j = bitCount - 1U; j > 0U; j-- )
- {
- i++;
-
- if( i >= max )
- {
- break;
- }
-
- c.c = buf[ i ];
-
- /* Additional bytes must match 10xxxxxx. */
- if( ( c.u & 0xC0U ) != 0x80U )
- {
- break;
- }
-
- value = ( value << 6U ) | ( c.u & 0x3FU );
- }
-
- if( ( j == 0U ) && ( shortestUTF8( bitCount, value ) == true ) )
- {
- *start = i + 1U;
- ret = true;
- }
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond an ASCII or UTF-8 code point.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a valid code point was present;
- * false otherwise.
- */
-static bool skipUTF8( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- if( *start < max )
- {
- if( isascii_( buf[ *start ] ) )
- {
- *start += 1U;
- ret = true;
- }
- else
- {
- ret = skipUTF8MultiByte( buf, start, max );
- }
- }
-
- return ret;
-}
-
-/**
- * @brief Convert a hexadecimal character to an integer.
- *
- * @param[in] c The character to convert.
- *
- * @return the integer value upon success or NOT_A_HEX_CHAR on failure.
- */
-#define NOT_A_HEX_CHAR ( 0x10U )
-static uint8_t hexToInt( char c )
-{
- char_ n;
-
- n.c = c;
-
- if( ( c >= 'a' ) && ( c <= 'f' ) )
- {
- n.c -= 'a';
- n.u += 10U;
- }
- else if( ( c >= 'A' ) && ( c <= 'F' ) )
- {
- n.c -= 'A';
- n.u += 10U;
- }
- else if( isdigit_( c ) )
- {
- n.c -= '0';
- }
- else
- {
- n.u = NOT_A_HEX_CHAR;
- }
-
- return n.u;
-}
-
-/**
- * @brief Advance buffer index beyond a single \u Unicode
- * escape sequence and output the value.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[out] outValue The value of the hex digits.
- *
- * @return true if a valid escape sequence was present;
- * false otherwise.
- *
- * @note For the sake of security, \u0000 is disallowed.
- */
-static bool skipOneHexEscape( const char * buf,
- size_t * start,
- size_t max,
- uint16_t * outValue )
-{
- bool ret = false;
- size_t i, end;
- uint16_t value = 0;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
- assert( outValue != NULL );
-
- i = *start;
-#define HEX_ESCAPE_LENGTH ( 6U ) /* e.g., \u1234 */
- /* MISRA Ref 14.3.1 [Configuration dependent invariant] */
- /* More details at: https://github.com/FreeRTOS/coreJSON/blob/main/MISRA.md#rule-143 */
- /* coverity[misra_c_2012_rule_14_3_violation] */
- end = ( i <= ( SIZE_MAX - HEX_ESCAPE_LENGTH ) ) ? ( i + HEX_ESCAPE_LENGTH ) : SIZE_MAX;
-
- if( ( end < max ) && ( buf[ i ] == '\\' ) && ( buf[ i + 1U ] == 'u' ) )
- {
- for( i += 2U; i < end; i++ )
- {
- uint8_t n = hexToInt( buf[ i ] );
-
- if( n == NOT_A_HEX_CHAR )
- {
- break;
- }
-
- value = ( value << 4U ) | n;
- }
- }
-
- if( ( i == end ) && ( value > 0U ) )
- {
- ret = true;
- *outValue = value;
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond one or a pair of \u Unicode escape sequences.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * Surrogate pairs are two escape sequences that together denote
- * a code point outside the Basic Multilingual Plane. They must
- * occur as a pair with the first "high" value in [U+D800, U+DBFF],
- * and the second "low" value in [U+DC00, U+DFFF].
- *
- * @return true if a valid escape sequence was present;
- * false otherwise.
- *
- * @note For the sake of security, \u0000 is disallowed.
- */
-#define isHighSurrogate( x ) ( ( ( x ) >= 0xD800U ) && ( ( x ) <= 0xDBFFU ) )
-#define isLowSurrogate( x ) ( ( ( x ) >= 0xDC00U ) && ( ( x ) <= 0xDFFFU ) )
-
-static bool skipHexEscape( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
- size_t i;
- uint16_t value;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- if( skipOneHexEscape( buf, &i, max, &value ) == true )
- {
- if( isHighSurrogate( value ) )
- {
- if( ( skipOneHexEscape( buf, &i, max, &value ) == true ) &&
- ( isLowSurrogate( value ) ) )
- {
- ret = true;
- }
- }
- else if( isLowSurrogate( value ) )
- {
- /* premature low surrogate */
- }
- else
- {
- ret = true;
- }
- }
-
- if( ret == true )
- {
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond an escape sequence.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a valid escape sequence was present;
- * false otherwise.
- *
- * @note For the sake of security, \NUL is disallowed.
- */
-static bool skipEscape( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- if( ( i < ( max - 1U ) ) && ( buf[ i ] == '\\' ) )
- {
- char c = buf[ i + 1U ];
-
- switch( c )
- {
- case '\0':
- break;
-
- case 'u':
- ret = skipHexEscape( buf, &i, max );
- break;
-
- case '"':
- case '\\':
- case '/':
- case 'b':
- case 'f':
- case 'n':
- case 'r':
- case 't':
- i += 2U;
- ret = true;
- break;
-
- default:
-
- /* a control character: (NUL,SPACE) */
- if( iscntrl_( c ) )
- {
- i += 2U;
- ret = true;
- }
-
- break;
- }
- }
-
- if( ret == true )
- {
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond a double-quoted string.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a valid string was present;
- * false otherwise.
- */
-static bool skipString( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- if( ( i < max ) && ( buf[ i ] == '"' ) )
- {
- i++;
-
- while( i < max )
- {
- if( buf[ i ] == '"' )
- {
- ret = true;
- i++;
- break;
- }
-
- if( buf[ i ] == '\\' )
- {
- if( skipEscape( buf, &i, max ) != true )
- {
- break;
- }
- }
- /* An unescaped control character is not allowed. */
- else if( iscntrl_( buf[ i ] ) )
- {
- break;
- }
- else if( skipUTF8( buf, &i, max ) != true )
- {
- break;
- }
- else
- {
- /* MISRA 15.7 */
- }
- }
- }
-
- if( ret == true )
- {
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Compare the leading n bytes of two character sequences.
- *
- * @param[in] a first character sequence
- * @param[in] b second character sequence
- * @param[in] n number of bytes
- *
- * @return true if the sequences are the same;
- * false otherwise
- */
-static bool strnEq( const char * a,
- const char * b,
- size_t n )
-{
- size_t i;
-
- assert( ( a != NULL ) && ( b != NULL ) );
-
- for( i = 0; i < n; i++ )
- {
- if( a[ i ] != b[ i ] )
- {
- break;
- }
- }
-
- return ( i == n ) ? true : false;
-}
-
-/**
- * @brief Advance buffer index beyond a literal.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[in] literal The type of literal.
- * @param[in] length The length of the literal.
- *
- * @return true if the literal was present;
- * false otherwise.
- */
-static bool skipLiteral( const char * buf,
- size_t * start,
- size_t max,
- const char * literal,
- size_t length )
-{
- bool ret = false;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
- assert( literal != NULL );
-
- if( ( *start < max ) && ( length <= ( max - *start ) ) )
- {
- ret = strnEq( &buf[ *start ], literal, length );
- }
-
- if( ret == true )
- {
- *start += length;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond a JSON literal.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a valid literal was present;
- * false otherwise.
- */
-static bool skipAnyLiteral( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
-
-#define skipLit_( x ) \
- ( skipLiteral( buf, start, max, ( x ), ( sizeof( x ) - 1UL ) ) == true )
-
- if( skipLit_( "true" ) || skipLit_( "false" ) || skipLit_( "null" ) )
- {
- ret = true;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond one or more digits.
- * Optionally, output the integer value of the digits.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[out] outValue The integer value of the digits.
- *
- * @note outValue may be NULL. If not NULL, and the output
- * exceeds ~2 billion, then -1 is output.
- *
- * @return true if a digit was present;
- * false otherwise.
- */
-#define MAX_FACTOR ( MAX_INDEX_VALUE / 10 )
-static bool skipDigits( const char * buf,
- size_t * start,
- size_t max,
- int32_t * outValue )
-{
- bool ret = false;
- size_t i, saveStart;
- int32_t value = 0;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- saveStart = *start;
-
- for( i = *start; i < max; i++ )
- {
- if( !isdigit_( buf[ i ] ) )
- {
- break;
- }
-
- if( ( outValue != NULL ) && ( value > -1 ) )
- {
- int8_t n = ( int8_t ) hexToInt( buf[ i ] );
-
- if( value <= MAX_FACTOR )
- {
- value = ( value * 10 ) + n;
- }
- else
- {
- value = -1;
- }
- }
- }
-
- if( i > saveStart )
- {
- ret = true;
- *start = i;
-
- if( outValue != NULL )
- {
- *outValue = value;
- }
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond the decimal portion of a number.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- */
-static void skipDecimals( const char * buf,
- size_t * start,
- size_t max )
-{
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- if( ( i < max ) && ( buf[ i ] == '.' ) )
- {
- i++;
-
- if( skipDigits( buf, &i, max, NULL ) == true )
- {
- *start = i;
- }
- }
-}
-
-/**
- * @brief Advance buffer index beyond the exponent portion of a number.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- */
-static void skipExponent( const char * buf,
- size_t * start,
- size_t max )
-{
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- if( ( i < max ) && ( ( buf[ i ] == 'e' ) || ( buf[ i ] == 'E' ) ) )
- {
- i++;
-
- if( ( i < max ) && ( ( buf[ i ] == '-' ) || ( buf[ i ] == '+' ) ) )
- {
- i++;
- }
-
- if( skipDigits( buf, &i, max, NULL ) == true )
- {
- *start = i;
- }
- }
-}
-
-/**
- * @brief Advance buffer index beyond a number.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a valid number was present;
- * false otherwise.
- */
-static bool skipNumber( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- if( ( i < max ) && ( buf[ i ] == '-' ) )
- {
- i++;
- }
-
- if( i < max )
- {
- /* JSON disallows superfluous leading zeroes, so an
- * initial zero must either be alone, or followed by
- * a decimal or exponent.
- *
- * Should there be a digit after the zero, that digit
- * will not be skipped by this function, and later parsing
- * will judge this an illegal document. */
- if( buf[ i ] == '0' )
- {
- ret = true;
- i++;
- }
- else
- {
- ret = skipDigits( buf, &i, max, NULL );
- }
- }
-
- if( ret == true )
- {
- skipDecimals( buf, &i, max );
- skipExponent( buf, &i, max );
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond a scalar value.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a scalar value was present;
- * false otherwise.
- */
-static bool skipAnyScalar( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
-
- if( ( skipString( buf, start, max ) == true ) ||
- ( skipAnyLiteral( buf, start, max ) == true ) ||
- ( skipNumber( buf, start, max ) == true ) )
- {
- ret = true;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond a comma separator
- * and surrounding whitespace.
- *
- * JSON uses a comma to separate values in an array and key-value
- * pairs in an object. JSON does not permit a trailing comma.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return true if a non-terminal comma was present;
- * false otherwise.
- */
-static bool skipSpaceAndComma( const char * buf,
- size_t * start,
- size_t max )
-{
- bool ret = false;
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- skipSpace( buf, start, max );
- i = *start;
-
- if( ( i < max ) && ( buf[ i ] == ',' ) )
- {
- i++;
- skipSpace( buf, &i, max );
-
- if( ( i < max ) && !isCloseBracket_( buf[ i ] ) )
- {
- ret = true;
- *start = i;
- }
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond the scalar values of an array.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @note Stops advance if a value is an object or array.
- */
-static void skipArrayScalars( const char * buf,
- size_t * start,
- size_t max )
-{
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- while( i < max )
- {
- if( skipAnyScalar( buf, &i, max ) != true )
- {
- break;
- }
-
- if( skipSpaceAndComma( buf, &i, max ) != true )
- {
- break;
- }
- }
-
- *start = i;
-}
-
-/**
- * @brief Advance buffer index beyond the scalar key-value pairs
- * of an object.
- *
- * In JSON, objects consist of comma-separated key-value pairs.
- * A key is always a string (a scalar) while a value may be a
- * scalar, an object, or an array. A colon must appear between
- * each key and value.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @note Stops advance if a value is an object or array.
- */
-static void skipObjectScalars( const char * buf,
- size_t * start,
- size_t max )
-{
- size_t i;
- bool comma;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- while( i < max )
- {
- if( skipString( buf, &i, max ) != true )
- {
- break;
- }
-
- skipSpace( buf, &i, max );
-
- if( ( i < max ) && ( buf[ i ] != ':' ) )
- {
- break;
- }
-
- i++;
- skipSpace( buf, &i, max );
-
- if( ( i < max ) && isOpenBracket_( buf[ i ] ) )
- {
- *start = i;
- break;
- }
-
- if( skipAnyScalar( buf, &i, max ) != true )
- {
- break;
- }
-
- comma = skipSpaceAndComma( buf, &i, max );
- *start = i;
-
- if( comma != true )
- {
- break;
- }
- }
-}
-
-/**
- * @brief Advance buffer index beyond one or more scalars.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[in] mode The first character of an array '[' or object '{'.
- */
-static void skipScalars( const char * buf,
- size_t * start,
- size_t max,
- char mode )
-{
- assert( isOpenBracket_( mode ) );
-
- skipSpace( buf, start, max );
-
- if( mode == '[' )
- {
- skipArrayScalars( buf, start, max );
- }
- else
- {
- skipObjectScalars( buf, start, max );
- }
-}
-
-/**
- * @brief Advance buffer index beyond a collection and handle nesting.
- *
- * A stack is used to continue parsing the prior collection type
- * when a nested collection is finished.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- *
- * @return #JSONSuccess if the buffer contents are a valid JSON collection;
- * #JSONIllegalDocument if the buffer contents are NOT valid JSON;
- * #JSONMaxDepthExceeded if object and array nesting exceeds a threshold;
- * #JSONPartial if the buffer contents are potentially valid but incomplete.
- */
-#ifndef JSON_MAX_DEPTH
- #define JSON_MAX_DEPTH 32
-#endif
-static JSONStatus_t skipCollection( const char * buf,
- size_t * start,
- size_t max )
-{
- JSONStatus_t ret = JSONPartial;
- char c, stack[ JSON_MAX_DEPTH ];
- int16_t depth = -1;
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
-
- i = *start;
-
- while( i < max )
- {
- c = buf[ i ];
- i++;
-
- switch( c )
- {
- case '{':
- case '[':
- depth++;
-
- if( depth == JSON_MAX_DEPTH )
- {
- ret = JSONMaxDepthExceeded;
- break;
- }
-
- stack[ depth ] = c;
- skipScalars( buf, &i, max, stack[ depth ] );
- break;
-
- case '}':
- case ']':
-
- if( ( depth > 0 ) && isMatchingBracket_( stack[ depth ], c ) )
- {
- depth--;
-
- if( skipSpaceAndComma( buf, &i, max ) == true )
- {
- skipScalars( buf, &i, max, stack[ depth ] );
- }
-
- break;
- }
-
- ret = ( ( depth == 0 ) && isMatchingBracket_( stack[ depth ], c ) ) ?
- JSONSuccess : JSONIllegalDocument;
- break;
-
- default:
- ret = JSONIllegalDocument;
- break;
- }
-
- if( ret != JSONPartial )
- {
- break;
- }
- }
-
- if( ret == JSONSuccess )
- {
- *start = i;
- }
-
- return ret;
-}
-
-/** @endcond */
-
-/**
- * See core_json.h for docs.
- *
- * Verify that the entire buffer contains exactly one scalar
- * or collection within optional whitespace.
- */
-JSONStatus_t JSON_Validate( const char * buf,
- size_t max )
-{
- JSONStatus_t ret;
- size_t i = 0;
-
- if( buf == NULL )
- {
- ret = JSONNullParameter;
- }
- else if( max == 0U )
- {
- ret = JSONBadParameter;
- }
- else
- {
- skipSpace( buf, &i, max );
-
- /** @cond DO_NOT_DOCUMENT */
- #ifndef JSON_VALIDATE_COLLECTIONS_ONLY
- if( skipAnyScalar( buf, &i, max ) == true )
- {
- ret = JSONSuccess;
- }
- else
- #endif
- /** @endcond */
- {
- ret = skipCollection( buf, &i, max );
- }
- }
-
- if( ( ret == JSONSuccess ) && ( i < max ) )
- {
- skipSpace( buf, &i, max );
-
- if( i != max )
- {
- ret = JSONIllegalDocument;
- }
- }
-
- return ret;
-}
-
-/** @cond DO_NOT_DOCUMENT */
-
-/**
- * @brief Output index and length for the next value.
- *
- * Also advances the buffer index beyond the value.
- * The value may be a scalar or a collection.
- * The start index should point to the beginning of the value.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[out] value A pointer to receive the index of the value.
- * @param[out] valueLength A pointer to receive the length of the value.
- *
- * @return true if a value was present;
- * false otherwise.
- */
-static bool nextValue( const char * buf,
- size_t * start,
- size_t max,
- size_t * value,
- size_t * valueLength )
-{
- bool ret = true;
- size_t i, valueStart;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
- assert( ( value != NULL ) && ( valueLength != NULL ) );
-
- i = *start;
- valueStart = i;
-
- if( ( skipAnyScalar( buf, &i, max ) == true ) ||
- ( skipCollection( buf, &i, max ) == JSONSuccess ) )
- {
- *value = valueStart;
- *valueLength = i - valueStart;
- }
- else
- {
- ret = false;
- }
-
- if( ret == true )
- {
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Output indexes for the next key-value pair of an object.
- *
- * Also advances the buffer index beyond the key-value pair.
- * The value may be a scalar or a collection.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[out] key A pointer to receive the index of the key.
- * @param[out] keyLength A pointer to receive the length of the key.
- * @param[out] value A pointer to receive the index of the value.
- * @param[out] valueLength A pointer to receive the length of the value.
- *
- * @return true if a key-value pair was present;
- * false otherwise.
- */
-static bool nextKeyValuePair( const char * buf,
- size_t * start,
- size_t max,
- size_t * key,
- size_t * keyLength,
- size_t * value,
- size_t * valueLength )
-{
- bool ret = true;
- size_t i, keyStart;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( max > 0U ) );
- assert( ( key != NULL ) && ( keyLength != NULL ) );
- assert( ( value != NULL ) && ( valueLength != NULL ) );
-
- i = *start;
- keyStart = i;
-
- if( skipString( buf, &i, max ) == true )
- {
- *key = keyStart + 1U;
- *keyLength = i - keyStart - 2U;
- }
- else
- {
- ret = false;
- }
-
- if( ret == true )
- {
- skipSpace( buf, &i, max );
-
- if( ( i < max ) && ( buf[ i ] == ':' ) )
- {
- i++;
- skipSpace( buf, &i, max );
- }
- else
- {
- ret = false;
- }
- }
-
- if( ret == true )
- {
- ret = nextValue( buf, &i, max, value, valueLength );
- }
-
- if( ret == true )
- {
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Find a key in a JSON object and output a pointer to its value.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] query The object keys and array indexes to search for.
- * @param[in] queryLength Length of the key.
- * @param[out] outValue A pointer to receive the index of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- *
- * Iterate over the key-value pairs of an object, looking for a matching key.
- *
- * @return true if the query is matched and the value output;
- * false otherwise.
- *
- * @note Parsing stops upon finding a match.
- */
-static bool objectSearch( const char * buf,
- size_t max,
- const char * query,
- size_t queryLength,
- size_t * outValue,
- size_t * outValueLength )
-{
- bool ret = false;
-
- size_t i = 0, key, keyLength, value = 0, valueLength = 0;
-
- assert( ( buf != NULL ) && ( query != NULL ) );
- assert( ( outValue != NULL ) && ( outValueLength != NULL ) );
-
- skipSpace( buf, &i, max );
-
- if( ( i < max ) && ( buf[ i ] == '{' ) )
- {
- i++;
- skipSpace( buf, &i, max );
-
- while( i < max )
- {
- if( nextKeyValuePair( buf, &i, max, &key, &keyLength,
- &value, &valueLength ) != true )
- {
- break;
- }
-
- if( ( queryLength == keyLength ) &&
- ( strnEq( query, &buf[ key ], keyLength ) == true ) )
- {
- ret = true;
- break;
- }
-
- if( skipSpaceAndComma( buf, &i, max ) != true )
- {
- break;
- }
- }
- }
-
- if( ret == true )
- {
- *outValue = value;
- *outValueLength = valueLength;
- }
-
- return ret;
-}
-
-/**
- * @brief Find an index in a JSON array and output a pointer to its value.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] queryIndex The index to search for.
- * @param[out] outValue A pointer to receive the index of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- *
- * Iterate over the values of an array, looking for a matching index.
- *
- * @return true if the queryIndex is found and the value output;
- * false otherwise.
- *
- * @note Parsing stops upon finding a match.
- */
-static bool arraySearch( const char * buf,
- size_t max,
- uint32_t queryIndex,
- size_t * outValue,
- size_t * outValueLength )
-{
- bool ret = false;
- size_t i = 0, value = 0, valueLength = 0;
- uint32_t currentIndex = 0;
-
- assert( buf != NULL );
- assert( ( outValue != NULL ) && ( outValueLength != NULL ) );
-
- skipSpace( buf, &i, max );
-
- if( ( i < max ) && ( buf[ i ] == '[' ) )
- {
- i++;
- skipSpace( buf, &i, max );
-
- while( i < max )
- {
- if( nextValue( buf, &i, max, &value, &valueLength ) != true )
- {
- break;
- }
-
- if( currentIndex == queryIndex )
- {
- ret = true;
- break;
- }
-
- if( skipSpaceAndComma( buf, &i, max ) != true )
- {
- break;
- }
-
- currentIndex++;
- }
- }
-
- if( ret == true )
- {
- *outValue = value;
- *outValueLength = valueLength;
- }
-
- return ret;
-}
-
-/**
- * @brief Advance buffer index beyond a query part.
- *
- * The part is the portion of the query which is not
- * a separator or array index.
- *
- * @param[in] buf The buffer to parse.
- * @param[in,out] start The index at which to begin.
- * @param[in] max The size of the buffer.
- * @param[out] outLength The length of the query part.
- *
- * @return true if a valid string was present;
- * false otherwise.
- */
-#ifndef JSON_QUERY_KEY_SEPARATOR
- #define JSON_QUERY_KEY_SEPARATOR '.'
-#endif
-#define isSeparator_( x ) ( ( x ) == JSON_QUERY_KEY_SEPARATOR )
-static bool skipQueryPart( const char * buf,
- size_t * start,
- size_t max,
- size_t * outLength )
-{
- bool ret = false;
- size_t i;
-
- assert( ( buf != NULL ) && ( start != NULL ) && ( outLength != NULL ) );
- assert( max > 0U );
-
- i = *start;
-
- while( ( i < max ) &&
- !isSeparator_( buf[ i ] ) &&
- !isSquareOpen_( buf[ i ] ) )
- {
- i++;
- }
-
- if( i > *start )
- {
- ret = true;
- *outLength = i - *start;
- *start = i;
- }
-
- return ret;
-}
-
-/**
- * @brief Handle a nested search by iterating over the parts of the query.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] query The object keys and array indexes to search for.
- * @param[in] queryLength Length of the key.
- * @param[out] outValue A pointer to receive the index of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- *
- * @return #JSONSuccess if the query is matched and the value output;
- * #JSONBadParameter if the query is empty, or any part is empty,
- * or an index is too large to convert;
- * #JSONNotFound if the query is NOT found.
- *
- * @note Parsing stops upon finding a match.
- */
-static JSONStatus_t multiSearch( const char * buf,
- size_t max,
- const char * query,
- size_t queryLength,
- size_t * outValue,
- size_t * outValueLength )
-{
- JSONStatus_t ret = JSONSuccess;
- size_t i = 0, start = 0, queryStart = 0, value = 0, length = max;
-
- assert( ( buf != NULL ) && ( query != NULL ) );
- assert( ( outValue != NULL ) && ( outValueLength != NULL ) );
- assert( ( max > 0U ) && ( queryLength > 0U ) );
-
- while( i < queryLength )
- {
- bool found = false;
-
- if( isSquareOpen_( query[ i ] ) )
- {
- int32_t queryIndex = -1;
- i++;
-
- ( void ) skipDigits( query, &i, queryLength, &queryIndex );
-
- if( ( queryIndex < 0 ) ||
- ( i >= queryLength ) || !isSquareClose_( query[ i ] ) )
- {
- ret = JSONBadParameter;
- break;
- }
-
- i++;
-
- found = arraySearch( &buf[ start ], length, ( uint32_t ) queryIndex, &value, &length );
- }
- else
- {
- size_t keyLength = 0;
-
- queryStart = i;
-
- if( ( skipQueryPart( query, &i, queryLength, &keyLength ) != true ) ||
- /* catch an empty key part or a trailing separator */
- ( i == ( queryLength - 1U ) ) )
- {
- ret = JSONBadParameter;
- break;
- }
-
- found = objectSearch( &buf[ start ], length, &query[ queryStart ], keyLength, &value, &length );
- }
-
- if( found == false )
- {
- ret = JSONNotFound;
- break;
- }
-
- start += value;
-
- if( ( i < queryLength ) && isSeparator_( query[ i ] ) )
- {
- i++;
- }
- }
-
- if( ret == JSONSuccess )
- {
- *outValue = start;
- *outValueLength = length;
- }
-
- return ret;
-}
-
-/**
- * @brief Return a JSON type based on a separator character or
- * the first character of a value.
- *
- * @param[in] c The character to classify.
- *
- * @return an enum of JSONTypes_t
- */
-static JSONTypes_t getType( char c )
-{
- JSONTypes_t t;
-
- switch( c )
- {
- case '"':
- t = JSONString;
- break;
-
- case '{':
- t = JSONObject;
- break;
-
- case '[':
- t = JSONArray;
- break;
-
- case 't':
- t = JSONTrue;
- break;
-
- case 'f':
- t = JSONFalse;
- break;
-
- case 'n':
- t = JSONNull;
- break;
-
- default:
- t = JSONNumber;
- break;
- }
-
- return t;
-}
-
-/** @endcond */
-
-/**
- * See core_json.h for docs.
- */
-JSONStatus_t JSON_SearchConst( const char * buf,
- size_t max,
- const char * query,
- size_t queryLength,
- const char ** outValue,
- size_t * outValueLength,
- JSONTypes_t * outType )
-{
- JSONStatus_t ret;
- size_t value = 0U;
-
- if( ( buf == NULL ) || ( query == NULL ) ||
- ( outValue == NULL ) || ( outValueLength == NULL ) )
- {
- ret = JSONNullParameter;
- }
- else if( ( max == 0U ) || ( queryLength == 0U ) )
- {
- ret = JSONBadParameter;
- }
- else
- {
- ret = multiSearch( buf, max, query, queryLength, &value, outValueLength );
- }
-
- if( ret == JSONSuccess )
- {
- JSONTypes_t t = getType( buf[ value ] );
-
- if( t == JSONString )
- {
- /* strip the surrounding quotes */
- value++;
- *outValueLength -= 2U;
- }
-
- *outValue = &buf[ value ];
-
- if( outType != NULL )
- {
- *outType = t;
- }
- }
-
- return ret;
-}
-
-/**
- * See core_json.h for docs.
- */
-JSONStatus_t JSON_SearchT( char * buf,
- size_t max,
- const char * query,
- size_t queryLength,
- char ** outValue,
- size_t * outValueLength,
- JSONTypes_t * outType )
-{
- /* MISRA Ref 11.3.1 [Misaligned access] */
- /* More details at: https://github.com/FreeRTOS/coreJSON/blob/main/MISRA.md#rule-113 */
- /* coverity[misra_c_2012_rule_11_3_violation] */
- return JSON_SearchConst( ( const char * ) buf, max, query, queryLength,
- ( const char ** ) outValue, outValueLength, outType );
-}
-
-/** @cond DO_NOT_DOCUMENT */
-
-/**
- * @brief Output the next key-value pair or value from a collection.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] start The index at which the collection begins.
- * @param[in,out] next The index at which to seek the next value.
- * @param[out] outKey A pointer to receive the index of the value found.
- * @param[out] outKeyLength A pointer to receive the length of the value found.
- * @param[out] outValue A pointer to receive the index of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- *
- * @return #JSONSuccess if a value is output;
- * #JSONIllegalDocument if the buffer does not begin with '[' or '{';
- * #JSONNotFound if there are no further values in the collection.
- */
-static JSONStatus_t iterate( const char * buf,
- size_t max,
- size_t * start,
- size_t * next,
- size_t * outKey,
- size_t * outKeyLength,
- size_t * outValue,
- size_t * outValueLength )
-{
- JSONStatus_t ret = JSONNotFound;
- bool found = false;
-
- assert( ( buf != NULL ) && ( max > 0U ) );
- assert( ( start != NULL ) && ( next != NULL ) );
- assert( ( outKey != NULL ) && ( outKeyLength != NULL ) );
- assert( ( outValue != NULL ) && ( outValueLength != NULL ) );
-
- if( *start < max )
- {
- switch( buf[ *start ] )
- {
- case '[':
- found = nextValue( buf, next, max, outValue, outValueLength );
-
- if( found == true )
- {
- *outKey = 0;
- *outKeyLength = 0;
- }
-
- break;
-
- case '{':
- found = nextKeyValuePair( buf, next, max, outKey, outKeyLength,
- outValue, outValueLength );
- break;
-
- default:
- ret = JSONIllegalDocument;
- break;
- }
- }
-
- if( found == true )
- {
- ret = JSONSuccess;
- ( void ) skipSpaceAndComma( buf, next, max );
- }
-
- return ret;
-}
-
-/** @endcond */
-
-/**
- * See core_json.h for docs.
- */
-JSONStatus_t JSON_Iterate( const char * buf,
- size_t max,
- size_t * start,
- size_t * next,
- JSONPair_t * outPair )
-{
- JSONStatus_t ret;
- size_t key, keyLength, value, valueLength;
-
- if( ( buf == NULL ) || ( start == NULL ) || ( next == NULL ) ||
- ( outPair == NULL ) )
- {
- ret = JSONNullParameter;
- }
- else if( ( max == 0U ) || ( *start >= max ) || ( *next > max ) )
- {
- ret = JSONBadParameter;
- }
- else
- {
- skipSpace( buf, start, max );
-
- if( *next <= *start )
- {
- *next = *start + 1U;
- skipSpace( buf, next, max );
- }
-
- ret = iterate( buf, max, start, next, &key, &keyLength,
- &value, &valueLength );
- }
-
- if( ret == JSONSuccess )
- {
- JSONTypes_t t = getType( buf[ value ] );
-
- if( t == JSONString )
- {
- /* strip the surrounding quotes */
- value++;
- valueLength -= 2U;
- }
-
- outPair->key = ( key == 0U ) ? NULL : &buf[ key ];
- outPair->keyLength = keyLength;
- outPair->value = &buf[ value ];
- outPair->valueLength = valueLength;
- outPair->jsonType = t;
- }
-
- return ret;
-}
diff --git a/project/coreMQTT/coreJSON/core_json.h b/project/coreMQTT/coreJSON/core_json.h
deleted file mode 100644
index 102a24f..0000000
--- a/project/coreMQTT/coreJSON/core_json.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * coreJSON v3.2.0
- * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_json.h
- * @brief Include this header file to use coreJSON in your application.
- */
-
-#ifndef CORE_JSON_H_
-#define CORE_JSON_H_
-
-#include <stdbool.h>
-#include <stddef.h>
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/**
- * @ingroup json_enum_types
- * @brief Return codes from coreJSON library functions.
- */
-typedef enum
-{
- JSONPartial = 0, /**< @brief JSON document is valid so far but incomplete. */
- JSONSuccess, /**< @brief JSON document is valid and complete. */
- JSONIllegalDocument, /**< @brief JSON document is invalid or malformed. */
- JSONMaxDepthExceeded, /**< @brief JSON document has nesting that exceeds JSON_MAX_DEPTH. */
- JSONNotFound, /**< @brief Query key could not be found in the JSON document. */
- JSONNullParameter, /**< @brief Pointer parameter passed to a function is NULL. */
- JSONBadParameter /**< @brief Query key is empty, or any subpart is empty, or max is 0. */
-} JSONStatus_t;
-
-/**
- * @brief Parse a buffer to determine if it contains a valid JSON document.
- *
- * @param[in] buf The buffer to parse.
- * @param[in] max The size of the buffer.
- *
- * @note The maximum nesting depth may be specified by defining the macro
- * JSON_MAX_DEPTH. The default is 32 of sizeof(char).
- *
- * @note By default, a valid JSON document may contain a single element
- * (e.g., string, boolean, number). To require that a valid document
- * contain an object or array, define JSON_VALIDATE_COLLECTIONS_ONLY.
- *
- * @return #JSONSuccess if the buffer contents are valid JSON;
- * #JSONNullParameter if buf is NULL;
- * #JSONBadParameter if max is 0;
- * #JSONIllegalDocument if the buffer contents are NOT valid JSON;
- * #JSONMaxDepthExceeded if object and array nesting exceeds a threshold;
- * #JSONPartial if the buffer contents are potentially valid but incomplete.
- *
- * <b>Example</b>
- * @code{c}
- * // Variables used in this example.
- * JSONStatus_t result;
- * char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}";
- * size_t bufferLength = sizeof( buffer ) - 1;
- *
- * result = JSON_Validate( buffer, bufferLength );
- *
- * // JSON document is valid.
- * assert( result == JSONSuccess );
- * @endcode
- */
-/* @[declare_json_validate] */
-JSONStatus_t JSON_Validate( const char * buf,
- size_t max );
-/* @[declare_json_validate] */
-
-/**
- * @brief Find a key or array index in a JSON document and output the
- * pointer @p outValue to its value.
- *
- * Any value may also be an object or an array to a maximum depth. A search
- * may descend through nested objects or arrays when the query contains matching
- * key strings or array indexes joined by a separator.
- *
- * For example, if the provided buffer contains <code>{"foo":"abc","bar":{"foo":"xyz"}}</code>,
- * then a search for 'foo' would output <code>abc</code>, 'bar' would output
- * <code>{"foo":"xyz"}</code>, and a search for 'bar.foo' would output
- * <code>xyz</code>.
- *
- * If the provided buffer contains <code>[123,456,{"foo":"abc","bar":[88,99]}]</code>,
- * then a search for '[1]' would output <code>456</code>, '[2].foo' would output
- * <code>abc</code>, and '[2].bar[0]' would output <code>88</code>.
- *
- * On success, the pointer @p outValue points to a location in buf. No null
- * termination is done for the value. For valid JSON it is safe to place
- * a null character at the end of the value, so long as the character
- * replaced is put back before running another search.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] query The object keys and array indexes to search for.
- * @param[in] queryLength Length of the key.
- * @param[out] outValue A pointer to receive the address of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- *
- * @note The maximum nesting depth may be specified by defining the macro
- * JSON_MAX_DEPTH. The default is 32 of sizeof(char).
- *
- * @note JSON_Search() performs validation, but stops upon finding a matching
- * key and its value. To validate the entire JSON document, use JSON_Validate().
- *
- * @return #JSONSuccess if the query is matched and the value output;
- * #JSONNullParameter if any pointer parameters are NULL;
- * #JSONBadParameter if the query is empty, or the portion after a separator is empty,
- * or max is 0, or an index is too large to convert to a signed 32-bit integer;
- * #JSONNotFound if the query has no match.
- *
- * <b>Example</b>
- * @code{c}
- * // Variables used in this example.
- * JSONStatus_t result;
- * char buffer[] = "{\"foo\":\"abc\",\"bar\":{\"foo\":\"xyz\"}}";
- * size_t bufferLength = sizeof( buffer ) - 1;
- * char query[] = "bar.foo";
- * size_t queryLength = sizeof( query ) - 1;
- * char * value;
- * size_t valueLength;
- *
- * // Calling JSON_Validate() is not necessary if the document is guaranteed to be valid.
- * result = JSON_Validate( buffer, bufferLength );
- *
- * if( result == JSONSuccess )
- * {
- * result = JSON_Search( buffer, bufferLength, query, queryLength,
- * &value, &valueLength );
- * }
- *
- * if( result == JSONSuccess )
- * {
- * // The pointer "value" will point to a location in the "buffer".
- * char save = value[ valueLength ];
- * // After saving the character, set it to a null byte for printing.
- * value[ valueLength ] = '\0';
- * // "Found: bar.foo -> xyz" will be printed.
- * printf( "Found: %s -> %s\n", query, value );
- * // Restore the original character.
- * value[ valueLength ] = save;
- * }
- * @endcode
- *
- * @note The maximum index value is ~2 billion ( 2^31 - 9 ).
- */
-/* @[declare_json_search] */
-#define JSON_Search( buf, max, query, queryLength, outValue, outValueLength ) \
- JSON_SearchT( buf, max, query, queryLength, outValue, outValueLength, NULL )
-/* @[declare_json_search] */
-
-/**
- * @brief The largest value usable as an array index in a query
- * for JSON_Search(), ~2 billion.
- */
-#define MAX_INDEX_VALUE ( 0x7FFFFFF7 ) /* 2^31 - 9 */
-
-/**
- * @ingroup json_enum_types
- * @brief Value types from the JSON standard.
- */
-typedef enum
-{
- JSONInvalid = 0, /**< @brief Not a valid JSON type. */
- JSONString, /**< @brief A quote delimited sequence of Unicode characters. */
- JSONNumber, /**< @brief A rational number. */
- JSONTrue, /**< @brief The literal value true. */
- JSONFalse, /**< @brief The literal value false. */
- JSONNull, /**< @brief The literal value null. */
- JSONObject, /**< @brief A collection of zero or more key-value pairs. */
- JSONArray /**< @brief A collection of zero or more values. */
-} JSONTypes_t;
-
-/**
- * @brief Same as JSON_Search(), but also outputs a type for the value found
- *
- * See @ref JSON_Search for documentation of common behavior.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] query The object keys and array indexes to search for.
- * @param[in] queryLength Length of the key.
- * @param[out] outValue A pointer to receive the address of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- * @param[out] outType An enum indicating the JSON-specific type of the value.
- */
-/* @[declare_json_searcht] */
-JSONStatus_t JSON_SearchT( char * buf,
- size_t max,
- const char * query,
- size_t queryLength,
- char ** outValue,
- size_t * outValueLength,
- JSONTypes_t * outType );
-/* @[declare_json_searcht] */
-
-/**
- * @brief Same as JSON_SearchT(), but with const qualified buf and outValue arguments.
- *
- * See @ref JSON_Search for documentation of common behavior.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in] query The object keys and array indexes to search for.
- * @param[in] queryLength Length of the key.
- * @param[out] outValue A pointer to receive the address of the value found.
- * @param[out] outValueLength A pointer to receive the length of the value found.
- * @param[out] outType An enum indicating the JSON-specific type of the value.
- */
-/* @[declare_json_searchconst] */
-JSONStatus_t JSON_SearchConst( const char * buf,
- size_t max,
- const char * query,
- size_t queryLength,
- const char ** outValue,
- size_t * outValueLength,
- JSONTypes_t * outType );
-/* @[declare_json_searchconst] */
-
-/**
- * @ingroup json_struct_types
- * @brief Structure to represent a key-value pair.
- */
-typedef struct
-{
- const char * key; /**< @brief Pointer to the code point sequence for key. */
- size_t keyLength; /**< @brief Length of the code point sequence for key. */
- const char * value; /**< @brief Pointer to the code point sequence for value. */
- size_t valueLength; /**< @brief Length of the code point sequence for value. */
- JSONTypes_t jsonType; /**< @brief JSON-specific type of the value. */
-} JSONPair_t;
-
-/**
- * @brief Output the next key-value pair or value from a collection.
- *
- * This function may be used in a loop to output each key-value pair from an object,
- * or each value from an array. For the first invocation, the integers pointed to by
- * start and next should be initialized to 0. These will be updated by the function.
- * If another key-value pair or value is present, the output structure is populated
- * and #JSONSuccess is returned; otherwise the structure is unchanged and #JSONNotFound
- * is returned.
- *
- * @param[in] buf The buffer to search.
- * @param[in] max size of the buffer.
- * @param[in,out] start The index at which the collection begins.
- * @param[in,out] next The index at which to seek the next value.
- * @param[out] outPair A pointer to receive the next key-value pair.
- *
- * @note This function expects a valid JSON document; run JSON_Validate() first.
- *
- * @note For an object, the outPair structure will reference a key and its value.
- * For an array, only the value will be referenced (i.e., outPair.key will be NULL).
- *
- * @return #JSONSuccess if a value is output;
- * #JSONIllegalDocument if the buffer does not contain a collection;
- * #JSONNotFound if there are no further values in the collection.
- *
- * <b>Example</b>
- * @code{c}
- * // Variables used in this example.
- * static char * json_types[] =
- * {
- * "invalid",
- * "string",
- * "number",
- * "true",
- * "false",
- * "null",
- * "object",
- * "array"
- * };
- *
- * void show( const char * json,
- * size_t length )
- * {
- * size_t start = 0, next = 0;
- * JSONPair_t pair = { 0 };
- * JSONStatus_t result;
- *
- * result = JSON_Validate( json, length );
- * if( result == JSONSuccess )
- * {
- * result = JSON_Iterate( json, length, &start, &next, &pair );
- * }
- *
- * while( result == JSONSuccess )
- * {
- * if( pair.key != NULL )
- * {
- * printf( "key: %.*s\t", ( int ) pair.keyLength, pair.key );
- * }
- *
- * printf( "value: (%s) %.*s\n", json_types[ pair.jsonType ],
- * ( int ) pair.valueLength, pair.value );
- *
- * result = JSON_Iterate( json, length, &start, &next, &pair );
- * }
- * }
- * @endcode
- */
-/* @[declare_json_iterate] */
-JSONStatus_t JSON_Iterate( const char * buf,
- size_t max,
- size_t * start,
- size_t * next,
- JSONPair_t * outPair );
-/* @[declare_json_iterate] */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_JSON_H_ */
diff --git a/project/coreMQTT/coreJSON/makefile b/project/coreMQTT/coreJSON/makefile
deleted file mode 100644
index b6ece0e..0000000
--- a/project/coreMQTT/coreJSON/makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#********************************************************************************
-# Copyright: (C) 2023 LingYun IoT System Studio
-# All rights reserved.
-#
-# Filename: Makefile
-# Description: This file used compile all the source code to static library
-#
-# Version: 1.0.0(11/08/23)
-# Author: Guo Wenxue <guowenxue@gmail.com>
-# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
-#
-#*******************************************************************************
-
-PWD=$(shell pwd )
-
-BUILD_ARCH=$(shell uname -m)
-ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
- CROSS_COMPILE?=arm-linux-gnueabihf-
-endif
-
-LIBNAME=$(shell basename ${PWD} )
-TOPDIR=$(shell dirname ${PWD} )
-CFLAGS+=-D_GNU_SOURCE
-
-all: clean
- @rm -f *.o
- @${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c
- ${CROSS_COMPILE}ar -rcs lib${LIBNAME}.a *.o
-
-clean:
- @rm -f *.o
- @rm -f *.a
-
-distclean:
- @make clean
diff --git a/project/coreMQTT/coreMQTT/README.md b/project/coreMQTT/coreMQTT/README.md
deleted file mode 100644
index 16355a1..0000000
--- a/project/coreMQTT/coreMQTT/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-## coreMQTT Client Library
-
-This repository contains the coreMQTT library that has been optimized for a low memory footprint. The coreMQTT library is compliant with the [MQTT 3.1.1](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html) standard. It has no dependencies on any additional libraries other than the standard C library, a customer-implemented network transport interface, and *optionally* a user-implemented platform time function. This library is distributed under the [MIT Open Source License](LICENSE).
-
-This library has gone through code quality checks including verification that no function has a [GNU Complexity](https://www.gnu.org/software/complexity/manual/complexity.html) score over 8, and checks against deviations from mandatory rules in the [MISRA coding standard](https://www.misra.org.uk). Deviations from the MISRA C:2012 guidelines are documented under [MISRA Deviations](MISRA.md). This library has also undergone both static code analysis from [Coverity static analysis](https://scan.coverity.com/), and validation of memory safety through the [CBMC automated reasoning tool](https://www.cprover.org/cbmc/).
-
-See memory requirements for this library [here](./docs/doxygen/include/size_table.md).
-
-**coreMQTT v2.1.1 [source code](https://github.com/FreeRTOS/coreMQTT/tree/v2.1.1/source) is part of the [FreeRTOS 202210.01 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202210.01-LTS) release.**
-
-## MQTT Config File
-
-The MQTT client library exposes build configuration macros that are required for building the library.
-A list of all the configurations and their default values are defined in [core_mqtt_config_defaults.h](source/include/core_mqtt_config_defaults.h).
-To provide custom values for the configuration macros, a custom config file named `core_mqtt_config.h` can be
-provided by the application to the library.
-
-By default, a `core_mqtt_config.h` custom config is required to build the library. To disable this requirement
-and build the library with default configuration values, provide `MQTT_DO_NOT_USE_CUSTOM_CONFIG` as a compile time preprocessor macro.
-
-**Thus, the MQTT library can be built by either**:
-* Defining a `core_mqtt_config.h` file in the application, and adding it to the include directories list of the library
-**OR**
-* Defining the `MQTT_DO_NOT_USE_CUSTOM_CONFIG` preprocessor macro for the library build.
-
-## Documentation
-
-For pre-generated documentation, please see the documentation linked in the locations below:
-
-| Location |
-| :-: |
-| [FreeRTOS.org](https://freertos.org/Documentation/api-ref/coreMQTT/docs/doxygen/output/html/index.html) |
-
-Note that the latest included version of coreMQTT may differ across repositories.
-
diff --git a/project/coreMQTT/coreMQTT/core_mqtt.c b/project/coreMQTT/coreMQTT/core_mqtt.c
deleted file mode 100644
index 633f61b..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt.c
+++ /dev/null
@@ -1,3314 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt.c
- * @brief Implements the user-facing functions in core_mqtt.h.
- */
-#include <string.h>
-#include <assert.h>
-
-#include "core_mqtt.h"
-#include "core_mqtt_state.h"
-
-/* Include config defaults header to get default values of configs. */
-#include "core_mqtt_config_defaults.h"
-
-#include "core_mqtt_default_logging.h"
-
-#ifndef MQTT_PRE_SEND_HOOK
-
-/**
- * @brief Hook called before a 'send' operation is executed.
- */
- #define MQTT_PRE_SEND_HOOK( pContext )
-#endif /* !MQTT_PRE_SEND_HOOK */
-
-#ifndef MQTT_POST_SEND_HOOK
-
-/**
- * @brief Hook called after the 'send' operation is complete.
- */
- #define MQTT_POST_SEND_HOOK( pContext )
-#endif /* !MQTT_POST_SEND_HOOK */
-
-#ifndef MQTT_PRE_STATE_UPDATE_HOOK
-
-/**
- * @brief Hook called just before an update to the MQTT state is made.
- */
- #define MQTT_PRE_STATE_UPDATE_HOOK( pContext )
-#endif /* !MQTT_PRE_STATE_UPDATE_HOOK */
-
-#ifndef MQTT_POST_STATE_UPDATE_HOOK
-
-/**
- * @brief Hook called just after an update to the MQTT state has
- * been made.
- */
- #define MQTT_POST_STATE_UPDATE_HOOK( pContext )
-#endif /* !MQTT_POST_STATE_UPDATE_HOOK */
-
-/*-----------------------------------------------------------*/
-
-/**
- * @brief Sends provided buffer to network using transport send.
- *
- * @brief param[in] pContext Initialized MQTT context.
- * @brief param[in] pBufferToSend Buffer to be sent to network.
- * @brief param[in] bytesToSend Number of bytes to be sent.
- *
- * @note This operation may call the transport send function
- * repeatedly to send bytes over the network until either:
- * 1. The requested number of bytes @a bytesToSend have been sent.
- * OR
- * 2. MQTT_SEND_TIMEOUT_MS milliseconds have gone by since entering this
- * function.
- * OR
- * 3. There is an error in sending data over the network.
- *
- * @return Total number of bytes sent, or negative value on network error.
- */
-static int32_t sendBuffer( MQTTContext_t * pContext,
- const uint8_t * pBufferToSend,
- size_t bytesToSend );
-
-/**
- * @brief Sends MQTT connect without copying the users data into any buffer.
- *
- * @brief param[in] pContext Initialized MQTT context.
- * @brief param[in] pConnectInfo MQTT CONNECT packet information.
- * @brief param[in] pWillInfo Last Will and Testament. Pass NULL if Last Will and
- * Testament is not used.
- * @brief param[in] remainingLength the length of the connect packet.
- *
- * @note This operation may call the transport send function
- * repeatedly to send bytes over the network until either:
- * 1. The requested number of bytes @a remainingLength have been sent.
- * OR
- * 2. MQTT_SEND_TIMEOUT_MS milliseconds have gone by since entering this
- * function.
- * OR
- * 3. There is an error in sending data over the network.
- *
- * @return #MQTTSendFailed or #MQTTSuccess.
- */
-static MQTTStatus_t sendConnectWithoutCopy( MQTTContext_t * pContext,
- const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength );
-
-/**
- * @brief Sends the vector array passed through the parameters over the network.
- *
- * @note The preference is given to 'writev' function if it is present in the
- * transport interface. Otherwise, a send call is made repeatedly to achieve the
- * result.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pIoVec The vector array to be sent.
- * @param[in] ioVecCount The number of elements in the array.
- *
- * @note This operation may call the transport send or writev functions
- * repeatedly to send bytes over the network until either:
- * 1. The requested number of bytes have been sent.
- * OR
- * 2. MQTT_SEND_TIMEOUT_MS milliseconds have gone by since entering this
- * function.
- * OR
- * 3. There is an error in sending data over the network.
- *
- * @return The total number of bytes sent or the error code as received from the
- * transport interface.
- */
-static int32_t sendMessageVector( MQTTContext_t * pContext,
- TransportOutVector_t * pIoVec,
- size_t ioVecCount );
-
-/**
- * @brief Add a string and its length after serializing it in a manner outlined by
- * the MQTT specification.
- *
- * @param[in] serailizedLength Array of two bytes to which the vector will point.
- * The array must remain in scope until the message has been sent.
- * @param[in] string The string to be serialized.
- * @param[in] length The length of the string to be serialized.
- * @param[in] iterator The iterator pointing to the first element in the
- * transport interface IO array.
- * @param[out] updatedLength This parameter will be added to with the number of
- * bytes added to the vector.
- *
- * @return The number of vectors added.
- */
-static size_t addEncodedStringToVector( uint8_t serailizedLength[ 2 ],
- const char * const string,
- uint16_t length,
- TransportOutVector_t * iterator,
- size_t * updatedLength );
-
-/**
- * @brief Send MQTT SUBSCRIBE message without copying the user data into a buffer and
- * directly sending it.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The count of elements in the list.
- * @param[in] packetId The packet ID of the subscribe packet
- * @param[in] remainingLength The remaining length of the subscribe packet.
- *
- * @return #MQTTSuccess or #MQTTSendFailed.
- */
-static MQTTStatus_t sendSubscribeWithoutCopy( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength );
-
-/**
- * @brief Send MQTT UNSUBSCRIBE message without copying the user data into a buffer and
- * directly sending it.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pSubscriptionList MQTT subscription info.
- * @param[in] subscriptionCount The count of elements in the list.
- * @param[in] packetId The packet ID of the unsubscribe packet.
- * @param[in] remainingLength The remaining length of the unsubscribe packet.
- *
- * @return #MQTTSuccess or #MQTTSendFailed.
- */
-static MQTTStatus_t sendUnsubscribeWithoutCopy( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength );
-
-/**
- * @brief Calculate the interval between two millisecond timestamps, including
- * when the later value has overflowed.
- *
- * @note In C, the operands are promoted to signed integers in subtraction.
- * Using this function avoids the need to cast the result of subtractions back
- * to uint32_t.
- *
- * @param[in] later The later time stamp, in milliseconds.
- * @param[in] start The earlier time stamp, in milliseconds.
- *
- * @return later - start.
- */
-static uint32_t calculateElapsedTime( uint32_t later,
- uint32_t start );
-
-/**
- * @brief Convert a byte indicating a publish ack type to an #MQTTPubAckType_t.
- *
- * @param[in] packetType First byte of fixed header.
- *
- * @return Type of ack.
- */
-static MQTTPubAckType_t getAckFromPacketType( uint8_t packetType );
-
-/**
- * @brief Receive bytes into the network buffer.
- *
- * @param[in] pContext Initialized MQTT Context.
- * @param[in] bytesToRecv Number of bytes to receive.
- *
- * @note This operation calls the transport receive function
- * repeatedly to read bytes from the network until either:
- * 1. The requested number of bytes @a bytesToRecv are read.
- * OR
- * 2. No data is received from the network for MQTT_RECV_POLLING_TIMEOUT_MS duration.
- *
- * OR
- * 3. There is an error in reading from the network.
- *
- *
- * @return Number of bytes received, or negative number on network error.
- */
-static int32_t recvExact( const MQTTContext_t * pContext,
- size_t bytesToRecv );
-
-/**
- * @brief Discard a packet from the transport interface.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] remainingLength Remaining length of the packet to dump.
- * @param[in] timeoutMs Time remaining to discard the packet.
- *
- * @return #MQTTRecvFailed or #MQTTNoDataAvailable.
- */
-static MQTTStatus_t discardPacket( const MQTTContext_t * pContext,
- size_t remainingLength,
- uint32_t timeoutMs );
-
-/**
- * @brief Discard a packet from the MQTT buffer and the transport interface.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] pPacketInfo Information struct of the packet to be discarded.
- *
- * @return #MQTTRecvFailed or #MQTTNoDataAvailable.
- */
-static MQTTStatus_t discardStoredPacket( MQTTContext_t * pContext,
- const MQTTPacketInfo_t * pPacketInfo );
-
-/**
- * @brief Receive a packet from the transport interface.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] incomingPacket packet struct with remaining length.
- * @param[in] remainingTimeMs Time remaining to receive the packet.
- *
- * @return #MQTTSuccess or #MQTTRecvFailed.
- */
-static MQTTStatus_t receivePacket( const MQTTContext_t * pContext,
- MQTTPacketInfo_t incomingPacket,
- uint32_t remainingTimeMs );
-
-/**
- * @brief Get the correct ack type to send.
- *
- * @param[in] state Current state of publish.
- *
- * @return Packet Type byte of PUBACK, PUBREC, PUBREL, or PUBCOMP if one of
- * those should be sent, else 0.
- */
-static uint8_t getAckTypeToSend( MQTTPublishState_t state );
-
-/**
- * @brief Send acks for received QoS 1/2 publishes.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] packetId packet ID of original PUBLISH.
- * @param[in] publishState Current publish state in record.
- *
- * @return #MQTTSuccess, #MQTTIllegalState or #MQTTSendFailed.
- */
-static MQTTStatus_t sendPublishAcks( MQTTContext_t * pContext,
- uint16_t packetId,
- MQTTPublishState_t publishState );
-
-/**
- * @brief Send a keep alive PINGREQ if the keep alive interval has elapsed.
- *
- * @param[in] pContext Initialized MQTT Context.
- *
- * @return #MQTTKeepAliveTimeout if a PINGRESP is not received in time,
- * #MQTTSendFailed if the PINGREQ cannot be sent, or #MQTTSuccess.
- */
-static MQTTStatus_t handleKeepAlive( MQTTContext_t * pContext );
-
-/**
- * @brief Handle received MQTT PUBLISH packet.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] pIncomingPacket Incoming packet.
- *
- * @return MQTTSuccess, MQTTIllegalState or deserialization error.
- */
-static MQTTStatus_t handleIncomingPublish( MQTTContext_t * pContext,
- MQTTPacketInfo_t * pIncomingPacket );
-
-/**
- * @brief Handle received MQTT publish acks.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] pIncomingPacket Incoming packet.
- *
- * @return MQTTSuccess, MQTTIllegalState, or deserialization error.
- */
-static MQTTStatus_t handlePublishAcks( MQTTContext_t * pContext,
- MQTTPacketInfo_t * pIncomingPacket );
-
-/**
- * @brief Handle received MQTT ack.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] pIncomingPacket Incoming packet.
- * @param[in] manageKeepAlive Flag indicating if PINGRESPs should not be given
- * to the application
- *
- * @return MQTTSuccess, MQTTIllegalState, or deserialization error.
- */
-static MQTTStatus_t handleIncomingAck( MQTTContext_t * pContext,
- MQTTPacketInfo_t * pIncomingPacket,
- bool manageKeepAlive );
-
-/**
- * @brief Run a single iteration of the receive loop.
- *
- * @param[in] pContext MQTT Connection context.
- * @param[in] manageKeepAlive Flag indicating if keep alive should be handled.
- *
- * @return #MQTTRecvFailed if a network error occurs during reception;
- * #MQTTSendFailed if a network error occurs while sending an ACK or PINGREQ;
- * #MQTTBadResponse if an invalid packet is received;
- * #MQTTKeepAliveTimeout if the server has not sent a PINGRESP before
- * #MQTT_PINGRESP_TIMEOUT_MS milliseconds;
- * #MQTTIllegalState if an incoming QoS 1/2 publish or ack causes an
- * invalid transition for the internal state machine;
- * #MQTTSuccess on success.
- */
-static MQTTStatus_t receiveSingleIteration( MQTTContext_t * pContext,
- bool manageKeepAlive );
-
-/**
- * @brief Validates parameters of #MQTT_Subscribe or #MQTT_Unsubscribe.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[in] packetId Packet identifier.
- *
- * @return #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- */
-static MQTTStatus_t validateSubscribeUnsubscribeParams( const MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId );
-
-/**
- * @brief Receives a CONNACK MQTT packet.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] timeoutMs Timeout for waiting for CONNACK packet.
- * @param[in] cleanSession Clean session flag set by application.
- * @param[out] pIncomingPacket List of MQTT subscription info.
- * @param[out] pSessionPresent Whether a previous session was present.
- * Only relevant if not establishing a clean session.
- *
- * @return #MQTTBadResponse if a bad response is received;
- * #MQTTNoDataAvailable if no data available for transport recv;
- * ##MQTTRecvFailed if transport recv failed;
- * #MQTTSuccess otherwise.
- */
-static MQTTStatus_t receiveConnack( const MQTTContext_t * pContext,
- uint32_t timeoutMs,
- bool cleanSession,
- MQTTPacketInfo_t * pIncomingPacket,
- bool * pSessionPresent );
-
-/**
- * @brief Resends pending acks for a re-established MQTT session, or
- * clears existing state records for a clean session.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] sessionPresent Session present flag received from the MQTT broker.
- *
- * @return #MQTTSendFailed if transport send during resend failed;
- * #MQTTSuccess otherwise.
- */
-static MQTTStatus_t handleSessionResumption( MQTTContext_t * pContext,
- bool sessionPresent );
-
-
-/**
- * @brief Send the publish packet without copying the topic string and payload in
- * the buffer.
- *
- * @brief param[in] pContext Initialized MQTT context.
- * @brief param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @brief param[in] pMqttHeader the serialized MQTT header with the header byte;
- * the encoded length of the packet; and the encoded length of the topic string.
- * @brief param[in] headerSize Size of the serialized PUBLISH header.
- * @brief param[in] packetId Packet Id of the publish packet.
- *
- * @return #MQTTSendFailed if transport send during resend failed;
- * #MQTTSuccess otherwise.
- */
-static MQTTStatus_t sendPublishWithoutCopy( MQTTContext_t * pContext,
- const MQTTPublishInfo_t * pPublishInfo,
- const uint8_t * pMqttHeader,
- size_t headerSize,
- uint16_t packetId );
-
-/**
- * @brief Function to validate #MQTT_Publish parameters.
- *
- * @brief param[in] pContext Initialized MQTT context.
- * @brief param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @brief param[in] packetId Packet Id for the MQTT PUBLISH packet.
- *
- * @return #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- */
-static MQTTStatus_t validatePublishParams( const MQTTContext_t * pContext,
- const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId );
-
-/**
- * @brief Performs matching for special cases when a topic filter ends
- * with a wildcard character.
- *
- * When the topic name has been consumed but there are remaining characters to
- * to match in topic filter, this function handles the following 2 cases:
- * - When the topic filter ends with "/+" or "/#" characters, but the topic
- * name only ends with '/'.
- * - When the topic filter ends with "/#" characters, but the topic name
- * ends at the parent level.
- *
- * @note This function ASSUMES that the topic name been consumed in linear
- * matching with the topic filer, but the topic filter has remaining characters
- * to be matched.
- *
- * @param[in] pTopicFilter The topic filter containing the wildcard.
- * @param[in] topicFilterLength Length of the topic filter being examined.
- * @param[in] filterIndex Index of the topic filter being examined.
- *
- * @return Returns whether the topic filter and the topic name match.
- */
-static bool matchEndWildcardsSpecialCases( const char * pTopicFilter,
- uint16_t topicFilterLength,
- uint16_t filterIndex );
-
-/**
- * @brief Attempt to match topic name with a topic filter starting with a wildcard.
- *
- * If the topic filter starts with a '+' (single-level) wildcard, the function
- * advances the @a pNameIndex by a level in the topic name.
- * If the topic filter starts with a '#' (multi-level) wildcard, the function
- * concludes that both the topic name and topic filter match.
- *
- * @param[in] pTopicName The topic name to match.
- * @param[in] topicNameLength Length of the topic name.
- * @param[in] pTopicFilter The topic filter to match.
- * @param[in] topicFilterLength Length of the topic filter.
- * @param[in,out] pNameIndex Current index in the topic name being examined. It is
- * advanced by one level for `+` wildcards.
- * @param[in, out] pFilterIndex Current index in the topic filter being examined.
- * It is advanced to position of '/' level separator for '+' wildcard.
- * @param[out] pMatch Whether the topic filter and topic name match.
- *
- * @return `true` if the caller of this function should exit; `false` if the
- * caller should continue parsing the topics.
- */
-static bool matchWildcards( const char * pTopicName,
- uint16_t topicNameLength,
- const char * pTopicFilter,
- uint16_t topicFilterLength,
- uint16_t * pNameIndex,
- uint16_t * pFilterIndex,
- bool * pMatch );
-
-/**
- * @brief Match a topic name and topic filter allowing the use of wildcards.
- *
- * @param[in] pTopicName The topic name to check.
- * @param[in] topicNameLength Length of the topic name.
- * @param[in] pTopicFilter The topic filter to check.
- * @param[in] topicFilterLength Length of topic filter.
- *
- * @return `true` if the topic name and topic filter match; `false` otherwise.
- */
-static bool matchTopicFilter( const char * pTopicName,
- uint16_t topicNameLength,
- const char * pTopicFilter,
- uint16_t topicFilterLength );
-
-/*-----------------------------------------------------------*/
-
-static bool matchEndWildcardsSpecialCases( const char * pTopicFilter,
- uint16_t topicFilterLength,
- uint16_t filterIndex )
-{
- bool matchFound = false;
-
- assert( pTopicFilter != NULL );
- assert( topicFilterLength != 0U );
-
- /* Check if the topic filter has 2 remaining characters and it ends in
- * "/#". This check handles the case to match filter "sport/#" with topic
- * "sport". The reason is that the '#' wildcard represents the parent and
- * any number of child levels in the topic name.*/
- if( ( topicFilterLength >= 3U ) &&
- ( filterIndex == ( topicFilterLength - 3U ) ) &&
- ( pTopicFilter[ filterIndex + 1U ] == '/' ) &&
- ( pTopicFilter[ filterIndex + 2U ] == '#' ) )
-
- {
- matchFound = true;
- }
-
- /* Check if the next character is "#" or "+" and the topic filter ends in
- * "/#" or "/+". This check handles the cases to match:
- *
- * - Topic filter "sport/+" with topic "sport/".
- * - Topic filter "sport/#" with topic "sport/".
- */
- if( ( filterIndex == ( topicFilterLength - 2U ) ) &&
- ( pTopicFilter[ filterIndex ] == '/' ) )
- {
- /* Check that the last character is a wildcard. */
- matchFound = ( pTopicFilter[ filterIndex + 1U ] == '+' ) ||
- ( pTopicFilter[ filterIndex + 1U ] == '#' );
- }
-
- return matchFound;
-}
-
-/*-----------------------------------------------------------*/
-
-static bool matchWildcards( const char * pTopicName,
- uint16_t topicNameLength,
- const char * pTopicFilter,
- uint16_t topicFilterLength,
- uint16_t * pNameIndex,
- uint16_t * pFilterIndex,
- bool * pMatch )
-{
- bool shouldStopMatching = false;
- bool locationIsValidForWildcard;
-
- assert( pTopicName != NULL );
- assert( topicNameLength != 0U );
- assert( pTopicFilter != NULL );
- assert( topicFilterLength != 0U );
- assert( pNameIndex != NULL );
- assert( pFilterIndex != NULL );
- assert( pMatch != NULL );
-
- /* Wild card in a topic filter is only valid either at the starting position
- * or when it is preceded by a '/'.*/
- locationIsValidForWildcard = ( *pFilterIndex == 0u ) ||
- ( pTopicFilter[ *pFilterIndex - 1U ] == '/' );
-
- if( ( pTopicFilter[ *pFilterIndex ] == '+' ) && ( locationIsValidForWildcard == true ) )
- {
- bool nextLevelExistsInTopicName = false;
- bool nextLevelExistsinTopicFilter = false;
-
- /* Move topic name index to the end of the current level. The end of the
- * current level is identified by the last character before the next level
- * separator '/'. */
- while( *pNameIndex < topicNameLength )
- {
- /* Exit the loop if we hit the level separator. */
- if( pTopicName[ *pNameIndex ] == '/' )
- {
- nextLevelExistsInTopicName = true;
- break;
- }
-
- ( *pNameIndex )++;
- }
-
- /* Determine if the topic filter contains a child level after the current level
- * represented by the '+' wildcard. */
- if( ( *pFilterIndex < ( topicFilterLength - 1U ) ) &&
- ( pTopicFilter[ *pFilterIndex + 1U ] == '/' ) )
- {
- nextLevelExistsinTopicFilter = true;
- }
-
- /* If the topic name contains a child level but the topic filter ends at
- * the current level, then there does not exist a match. */
- if( ( nextLevelExistsInTopicName == true ) &&
- ( nextLevelExistsinTopicFilter == false ) )
- {
- *pMatch = false;
- shouldStopMatching = true;
- }
-
- /* If the topic name and topic filter have child levels, then advance the
- * filter index to the level separator in the topic filter, so that match
- * can be performed in the next level.
- * Note: The name index already points to the level separator in the topic
- * name. */
- else if( nextLevelExistsInTopicName == true )
- {
- ( *pFilterIndex )++;
- }
- else
- {
- /* If we have reached here, the the loop terminated on the
- * ( *pNameIndex < topicNameLength) condition, which means that have
- * reached past the end of the topic name, and thus, we decrement the
- * index to the last character in the topic name.*/
- ( *pNameIndex )--;
- }
- }
-
- /* '#' matches everything remaining in the topic name. It must be the
- * last character in a topic filter. */
- else if( ( pTopicFilter[ *pFilterIndex ] == '#' ) &&
- ( *pFilterIndex == ( topicFilterLength - 1U ) ) &&
- ( locationIsValidForWildcard == true ) )
- {
- /* Subsequent characters don't need to be checked for the
- * multi-level wildcard. */
- *pMatch = true;
- shouldStopMatching = true;
- }
- else
- {
- /* Any character mismatch other than '+' or '#' means the topic
- * name does not match the topic filter. */
- *pMatch = false;
- shouldStopMatching = true;
- }
-
- return shouldStopMatching;
-}
-
-/*-----------------------------------------------------------*/
-
-static bool matchTopicFilter( const char * pTopicName,
- uint16_t topicNameLength,
- const char * pTopicFilter,
- uint16_t topicFilterLength )
-{
- bool matchFound = false, shouldStopMatching = false;
- uint16_t nameIndex = 0, filterIndex = 0;
-
- assert( pTopicName != NULL );
- assert( topicNameLength != 0 );
- assert( pTopicFilter != NULL );
- assert( topicFilterLength != 0 );
-
- while( ( nameIndex < topicNameLength ) && ( filterIndex < topicFilterLength ) )
- {
- /* Check if the character in the topic name matches the corresponding
- * character in the topic filter string. */
- if( pTopicName[ nameIndex ] == pTopicFilter[ filterIndex ] )
- {
- /* If the topic name has been consumed but the topic filter has not
- * been consumed, match for special cases when the topic filter ends
- * with wildcard character. */
- if( nameIndex == ( topicNameLength - 1U ) )
- {
- matchFound = matchEndWildcardsSpecialCases( pTopicFilter,
- topicFilterLength,
- filterIndex );
- }
- }
- else
- {
- /* Check for matching wildcards. */
- shouldStopMatching = matchWildcards( pTopicName,
- topicNameLength,
- pTopicFilter,
- topicFilterLength,
- &nameIndex,
- &filterIndex,
- &matchFound );
- }
-
- if( ( matchFound == true ) || ( shouldStopMatching == true ) )
- {
- break;
- }
-
- /* Increment indexes. */
- nameIndex++;
- filterIndex++;
- }
-
- if( matchFound == false )
- {
- /* If the end of both strings has been reached, they match. This represents the
- * case when the topic filter contains the '+' wildcard at a non-starting position.
- * For example, when matching either of "sport/+/player" OR "sport/hockey/+" topic
- * filters with "sport/hockey/player" topic name. */
- matchFound = ( nameIndex == topicNameLength ) &&
- ( filterIndex == topicFilterLength );
- }
-
- return matchFound;
-}
-
-/*-----------------------------------------------------------*/
-
-static int32_t sendMessageVector( MQTTContext_t * pContext,
- TransportOutVector_t * pIoVec,
- size_t ioVecCount )
-{
- int32_t sendResult;
- uint32_t timeoutMs;
- TransportOutVector_t * pIoVectIterator;
- size_t vectorsToBeSent = ioVecCount;
- size_t bytesToSend = 0U;
- int32_t bytesSentOrError = 0;
-
- assert( pContext != NULL );
- assert( pIoVec != NULL );
- assert( pContext->getTime != NULL );
- /* Send must always be defined */
- assert( pContext->transportInterface.send != NULL );
-
- /* Count the total number of bytes to be sent as outlined in the vector. */
- for( pIoVectIterator = pIoVec; pIoVectIterator <= &( pIoVec[ ioVecCount - 1U ] ); pIoVectIterator++ )
- {
- bytesToSend += pIoVectIterator->iov_len;
- }
-
- /* Reset the iterator to point to the first entry in the array. */
- pIoVectIterator = pIoVec;
-
- /* Set the timeout. */
- timeoutMs = pContext->getTime() + MQTT_SEND_TIMEOUT_MS;
-
- while( ( bytesSentOrError < ( int32_t ) bytesToSend ) && ( bytesSentOrError >= 0 ) )
- {
- if( pContext->transportInterface.writev != NULL )
- {
- sendResult = pContext->transportInterface.writev( pContext->transportInterface.pNetworkContext,
- pIoVectIterator,
- vectorsToBeSent );
- }
- else
- {
- sendResult = pContext->transportInterface.send( pContext->transportInterface.pNetworkContext,
- pIoVectIterator->iov_base,
- pIoVectIterator->iov_len );
- }
-
- if( sendResult > 0 )
- {
- /* It is a bug in the application's transport send implementation if
- * more bytes than expected are sent. */
- assert( sendResult <= ( ( int32_t ) bytesToSend - bytesSentOrError ) );
-
- bytesSentOrError += sendResult;
-
- /* Set last transmission time. */
- pContext->lastPacketTxTime = pContext->getTime();
-
- LogDebug( ( "sendMessageVector: Bytes Sent=%ld, Bytes Remaining=%lu",
- ( long int ) sendResult,
- ( unsigned long ) ( bytesToSend - ( size_t ) bytesSentOrError ) ) );
- }
- else if( sendResult < 0 )
- {
- bytesSentOrError = sendResult;
- LogError( ( "sendMessageVector: Unable to send packet: Network Error." ) );
- }
- else
- {
- /* MISRA Empty body */
- }
-
- /* Check for timeout. */
- if( pContext->getTime() >= timeoutMs )
- {
- LogError( ( "sendMessageVector: Unable to send packet: Timed out." ) );
- break;
- }
-
- /* Update the send pointer to the correct vector and offset. */
- while( ( pIoVectIterator <= &( pIoVec[ ioVecCount - 1U ] ) ) &&
- ( sendResult >= ( int32_t ) pIoVectIterator->iov_len ) )
- {
- sendResult -= ( int32_t ) pIoVectIterator->iov_len;
- pIoVectIterator++;
- /* Update the number of vector which are yet to be sent. */
- vectorsToBeSent--;
- }
-
- /* Some of the bytes from this vector were sent as well, update the length
- * and the pointer to data in this vector. */
- if( ( sendResult > 0 ) &&
- ( pIoVectIterator <= &( pIoVec[ ioVecCount - 1U ] ) ) )
- {
- pIoVectIterator->iov_base = ( const void * ) &( ( ( const uint8_t * ) pIoVectIterator->iov_base )[ sendResult ] );
- pIoVectIterator->iov_len -= ( size_t ) sendResult;
- }
- }
-
- return bytesSentOrError;
-}
-
-static int32_t sendBuffer( MQTTContext_t * pContext,
- const uint8_t * pBufferToSend,
- size_t bytesToSend )
-{
- int32_t sendResult;
- uint32_t timeoutMs;
- int32_t bytesSentOrError = 0;
- const uint8_t * pIndex = pBufferToSend;
-
- assert( pContext != NULL );
- assert( pContext->getTime != NULL );
- assert( pContext->transportInterface.send != NULL );
- assert( pIndex != NULL );
-
- /* Set the timeout. */
- timeoutMs = pContext->getTime() + MQTT_SEND_TIMEOUT_MS;
-
- while( ( bytesSentOrError < ( int32_t ) bytesToSend ) && ( bytesSentOrError >= 0 ) )
- {
- sendResult = pContext->transportInterface.send( pContext->transportInterface.pNetworkContext,
- pIndex,
- bytesToSend - ( size_t ) bytesSentOrError );
-
- if( sendResult > 0 )
- {
- /* It is a bug in the application's transport send implementation if
- * more bytes than expected are sent. */
- assert( sendResult <= ( ( int32_t ) bytesToSend - bytesSentOrError ) );
-
- bytesSentOrError += sendResult;
- pIndex = &pIndex[ sendResult ];
-
- /* Set last transmission time. */
- pContext->lastPacketTxTime = pContext->getTime();
-
- LogDebug( ( "sendBuffer: Bytes Sent=%ld, Bytes Remaining=%lu",
- ( long int ) sendResult,
- ( unsigned long ) ( bytesToSend - ( size_t ) bytesSentOrError ) ) );
- }
- else if( sendResult < 0 )
- {
- bytesSentOrError = sendResult;
- LogError( ( "sendBuffer: Unable to send packet: Network Error." ) );
- }
- else
- {
- /* MISRA Empty body */
- }
-
- /* Check for timeout. */
- if( pContext->getTime() >= timeoutMs )
- {
- LogError( ( "sendBuffer: Unable to send packet: Timed out." ) );
- break;
- }
- }
-
- return bytesSentOrError;
-}
-
-/*-----------------------------------------------------------*/
-
-static uint32_t calculateElapsedTime( uint32_t later,
- uint32_t start )
-{
- return later - start;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTPubAckType_t getAckFromPacketType( uint8_t packetType )
-{
- MQTTPubAckType_t ackType = MQTTPuback;
-
- switch( packetType )
- {
- case MQTT_PACKET_TYPE_PUBACK:
- ackType = MQTTPuback;
- break;
-
- case MQTT_PACKET_TYPE_PUBREC:
- ackType = MQTTPubrec;
- break;
-
- case MQTT_PACKET_TYPE_PUBREL:
- ackType = MQTTPubrel;
- break;
-
- case MQTT_PACKET_TYPE_PUBCOMP:
- default:
-
- /* This function is only called after checking the type is one of
- * the above four values, so packet type must be PUBCOMP here. */
- assert( packetType == MQTT_PACKET_TYPE_PUBCOMP );
- ackType = MQTTPubcomp;
- break;
- }
-
- return ackType;
-}
-
-/*-----------------------------------------------------------*/
-
-static int32_t recvExact( const MQTTContext_t * pContext,
- size_t bytesToRecv )
-{
- uint8_t * pIndex = NULL;
- size_t bytesRemaining = bytesToRecv;
- int32_t totalBytesRecvd = 0, bytesRecvd;
- uint32_t lastDataRecvTimeMs = 0U, timeSinceLastRecvMs = 0U;
- TransportRecv_t recvFunc = NULL;
- MQTTGetCurrentTimeFunc_t getTimeStampMs = NULL;
- bool receiveError = false;
-
- assert( pContext != NULL );
- assert( bytesToRecv <= pContext->networkBuffer.size );
- assert( pContext->getTime != NULL );
- assert( pContext->transportInterface.recv != NULL );
- assert( pContext->networkBuffer.pBuffer != NULL );
-
- pIndex = pContext->networkBuffer.pBuffer;
- recvFunc = pContext->transportInterface.recv;
- getTimeStampMs = pContext->getTime;
-
- /* Part of the MQTT packet has been read before calling this function. */
- lastDataRecvTimeMs = getTimeStampMs();
-
- while( ( bytesRemaining > 0U ) && ( receiveError == false ) )
- {
- bytesRecvd = recvFunc( pContext->transportInterface.pNetworkContext,
- pIndex,
- bytesRemaining );
-
- if( bytesRecvd < 0 )
- {
- LogError( ( "Network error while receiving packet: ReturnCode=%ld.",
- ( long int ) bytesRecvd ) );
- totalBytesRecvd = bytesRecvd;
- receiveError = true;
- }
- else if( bytesRecvd > 0 )
- {
- /* Reset the starting time as we have received some data from the network. */
- lastDataRecvTimeMs = getTimeStampMs();
-
- /* It is a bug in the application's transport receive implementation
- * if more bytes than expected are received. To avoid a possible
- * overflow in converting bytesRemaining from unsigned to signed,
- * this assert must exist after the check for bytesRecvd being
- * negative. */
- assert( ( size_t ) bytesRecvd <= bytesRemaining );
-
- bytesRemaining -= ( size_t ) bytesRecvd;
- totalBytesRecvd += ( int32_t ) bytesRecvd;
- /* Increment the index. */
- pIndex = &pIndex[ bytesRecvd ];
- LogDebug( ( "BytesReceived=%ld, BytesRemaining=%lu, TotalBytesReceived=%ld.",
- ( long int ) bytesRecvd,
- ( unsigned long ) bytesRemaining,
- ( long int ) totalBytesRecvd ) );
- }
- else
- {
- /* No bytes were read from the network. */
- timeSinceLastRecvMs = calculateElapsedTime( getTimeStampMs(), lastDataRecvTimeMs );
-
- /* Check for timeout if we have been waiting to receive any byte on the network. */
- if( timeSinceLastRecvMs >= MQTT_RECV_POLLING_TIMEOUT_MS )
- {
- LogError( ( "Unable to receive packet: Timed out in transport recv." ) );
- receiveError = true;
- }
- }
- }
-
- return totalBytesRecvd;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t discardPacket( const MQTTContext_t * pContext,
- size_t remainingLength,
- uint32_t timeoutMs )
-{
- MQTTStatus_t status = MQTTRecvFailed;
- int32_t bytesReceived = 0;
- size_t bytesToReceive = 0U;
- uint32_t totalBytesReceived = 0U;
- uint32_t entryTimeMs = 0U;
- uint32_t elapsedTimeMs = 0U;
- MQTTGetCurrentTimeFunc_t getTimeStampMs = NULL;
- bool receiveError = false;
-
- assert( pContext != NULL );
- assert( pContext->getTime != NULL );
-
- bytesToReceive = pContext->networkBuffer.size;
- getTimeStampMs = pContext->getTime;
-
- entryTimeMs = getTimeStampMs();
-
- while( ( totalBytesReceived < remainingLength ) && ( receiveError == false ) )
- {
- if( ( remainingLength - totalBytesReceived ) < bytesToReceive )
- {
- bytesToReceive = remainingLength - totalBytesReceived;
- }
-
- bytesReceived = recvExact( pContext, bytesToReceive );
-
- if( bytesReceived != ( int32_t ) bytesToReceive )
- {
- LogError( ( "Receive error while discarding packet."
- "ReceivedBytes=%ld, ExpectedBytes=%lu.",
- ( long int ) bytesReceived,
- ( unsigned long ) bytesToReceive ) );
- receiveError = true;
- }
- else
- {
- totalBytesReceived += ( uint32_t ) bytesReceived;
-
- elapsedTimeMs = calculateElapsedTime( getTimeStampMs(), entryTimeMs );
-
- /* Check for timeout. */
- if( elapsedTimeMs >= timeoutMs )
- {
- LogError( ( "Time expired while discarding packet." ) );
- receiveError = true;
- }
- }
- }
-
- if( totalBytesReceived == remainingLength )
- {
- LogError( ( "Dumped packet. DumpedBytes=%lu.",
- ( unsigned long ) totalBytesReceived ) );
- /* Packet dumped, so no data is available. */
- status = MQTTNoDataAvailable;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t discardStoredPacket( MQTTContext_t * pContext,
- const MQTTPacketInfo_t * pPacketInfo )
-{
- MQTTStatus_t status = MQTTRecvFailed;
- int32_t bytesReceived = 0;
- size_t bytesToReceive = 0U;
- uint32_t totalBytesReceived = 0U;
- bool receiveError = false;
- size_t mqttPacketSize = 0;
- size_t remainingLength;
-
- assert( pContext != NULL );
- assert( pPacketInfo != NULL );
-
- mqttPacketSize = pPacketInfo->remainingLength + pPacketInfo->headerLength;
-
- /* Assert that the packet being discarded is bigger than the
- * receive buffer. */
- assert( mqttPacketSize > pContext->networkBuffer.size );
-
- /* Discard these many bytes at a time. */
- bytesToReceive = pContext->networkBuffer.size;
-
- /* Number of bytes depicted by 'index' have already been received. */
- remainingLength = mqttPacketSize - pContext->index;
-
- while( ( totalBytesReceived < remainingLength ) && ( receiveError == false ) )
- {
- if( ( remainingLength - totalBytesReceived ) < bytesToReceive )
- {
- bytesToReceive = remainingLength - totalBytesReceived;
- }
-
- bytesReceived = recvExact( pContext, bytesToReceive );
-
- if( bytesReceived != ( int32_t ) bytesToReceive )
- {
- LogError( ( "Receive error while discarding packet."
- "ReceivedBytes=%ld, ExpectedBytes=%lu.",
- ( long int ) bytesReceived,
- ( unsigned long ) bytesToReceive ) );
- receiveError = true;
- }
- else
- {
- totalBytesReceived += ( uint32_t ) bytesReceived;
- }
- }
-
- if( totalBytesReceived == remainingLength )
- {
- LogError( ( "Dumped packet. DumpedBytes=%lu.",
- ( unsigned long ) totalBytesReceived ) );
- /* Packet dumped, so no data is available. */
- status = MQTTNoDataAvailable;
- }
-
- /* Clear the buffer */
- ( void ) memset( pContext->networkBuffer.pBuffer,
- 0,
- pContext->networkBuffer.size );
-
- /* Reset the index. */
- pContext->index = 0;
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t receivePacket( const MQTTContext_t * pContext,
- MQTTPacketInfo_t incomingPacket,
- uint32_t remainingTimeMs )
-{
- MQTTStatus_t status = MQTTSuccess;
- int32_t bytesReceived = 0;
- size_t bytesToReceive = 0U;
-
- assert( pContext != NULL );
- assert( pContext->networkBuffer.pBuffer != NULL );
-
- if( incomingPacket.remainingLength > pContext->networkBuffer.size )
- {
- LogError( ( "Incoming packet will be dumped: "
- "Packet length exceeds network buffer size."
- "PacketSize=%lu, NetworkBufferSize=%lu.",
- ( unsigned long ) incomingPacket.remainingLength,
- ( unsigned long ) pContext->networkBuffer.size ) );
- status = discardPacket( pContext,
- incomingPacket.remainingLength,
- remainingTimeMs );
- }
- else
- {
- bytesToReceive = incomingPacket.remainingLength;
- bytesReceived = recvExact( pContext, bytesToReceive );
-
- if( bytesReceived == ( int32_t ) bytesToReceive )
- {
- /* Receive successful, bytesReceived == bytesToReceive. */
- LogDebug( ( "Packet received. ReceivedBytes=%ld.",
- ( long int ) bytesReceived ) );
- }
- else
- {
- LogError( ( "Packet reception failed. ReceivedBytes=%ld, "
- "ExpectedBytes=%lu.",
- ( long int ) bytesReceived,
- ( unsigned long ) bytesToReceive ) );
- status = MQTTRecvFailed;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static uint8_t getAckTypeToSend( MQTTPublishState_t state )
-{
- uint8_t packetTypeByte = 0U;
-
- switch( state )
- {
- case MQTTPubAckSend:
- packetTypeByte = MQTT_PACKET_TYPE_PUBACK;
- break;
-
- case MQTTPubRecSend:
- packetTypeByte = MQTT_PACKET_TYPE_PUBREC;
- break;
-
- case MQTTPubRelSend:
- packetTypeByte = MQTT_PACKET_TYPE_PUBREL;
- break;
-
- case MQTTPubCompSend:
- packetTypeByte = MQTT_PACKET_TYPE_PUBCOMP;
- break;
-
- case MQTTPubAckPending:
- case MQTTPubCompPending:
- case MQTTPubRecPending:
- case MQTTPubRelPending:
- case MQTTPublishDone:
- case MQTTPublishSend:
- case MQTTStateNull:
- default:
- /* Take no action for states that do not require sending an ack. */
- break;
- }
-
- return packetTypeByte;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t sendPublishAcks( MQTTContext_t * pContext,
- uint16_t packetId,
- MQTTPublishState_t publishState )
-{
- MQTTStatus_t status = MQTTSuccess;
- MQTTPublishState_t newState = MQTTStateNull;
- int32_t sendResult = 0;
- uint8_t packetTypeByte = 0U;
- MQTTPubAckType_t packetType;
- MQTTFixedBuffer_t localBuffer;
- uint8_t pubAckPacket[ MQTT_PUBLISH_ACK_PACKET_SIZE ];
-
- localBuffer.pBuffer = pubAckPacket;
- localBuffer.size = MQTT_PUBLISH_ACK_PACKET_SIZE;
-
- assert( pContext != NULL );
-
- packetTypeByte = getAckTypeToSend( publishState );
-
- if( packetTypeByte != 0U )
- {
- packetType = getAckFromPacketType( packetTypeByte );
-
- status = MQTT_SerializeAck( &localBuffer,
- packetTypeByte,
- packetId );
-
- if( status == MQTTSuccess )
- {
- MQTT_PRE_SEND_HOOK( pContext );
-
- /* Here, we are not using the vector approach for efficiency. There is just one buffer
- * to be sent which can be achieved with a normal send call. */
- sendResult = sendBuffer( pContext,
- localBuffer.pBuffer,
- MQTT_PUBLISH_ACK_PACKET_SIZE );
-
- MQTT_POST_SEND_HOOK( pContext );
- }
-
- if( sendResult == ( int32_t ) MQTT_PUBLISH_ACK_PACKET_SIZE )
- {
- pContext->controlPacketSent = true;
-
- MQTT_PRE_STATE_UPDATE_HOOK( pContext );
-
- status = MQTT_UpdateStateAck( pContext,
- packetId,
- packetType,
- MQTT_SEND,
- &newState );
-
- MQTT_POST_STATE_UPDATE_HOOK( pContext );
-
- if( status != MQTTSuccess )
- {
- LogError( ( "Failed to update state of publish %hu.",
- ( unsigned short ) packetId ) );
- }
- }
- else
- {
- LogError( ( "Failed to send ACK packet: PacketType=%02x, SentBytes=%ld, "
- "PacketSize=%lu.",
- ( unsigned int ) packetTypeByte, ( long int ) sendResult,
- MQTT_PUBLISH_ACK_PACKET_SIZE ) );
- status = MQTTSendFailed;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t handleKeepAlive( MQTTContext_t * pContext )
-{
- MQTTStatus_t status = MQTTSuccess;
- uint32_t now = 0U;
- uint32_t packetTxTimeoutMs = 0U;
-
- assert( pContext != NULL );
- assert( pContext->getTime != NULL );
-
- now = pContext->getTime();
-
- packetTxTimeoutMs = 1000U * ( uint32_t ) pContext->keepAliveIntervalSec;
-
- if( PACKET_TX_TIMEOUT_MS < packetTxTimeoutMs )
- {
- packetTxTimeoutMs = PACKET_TX_TIMEOUT_MS;
- }
-
- /* If keep alive interval is 0, it is disabled. */
- if( pContext->waitingForPingResp == true )
- {
- /* Has time expired? */
- if( calculateElapsedTime( now, pContext->pingReqSendTimeMs ) >
- MQTT_PINGRESP_TIMEOUT_MS )
- {
- status = MQTTKeepAliveTimeout;
- }
- }
- else
- {
- if( ( packetTxTimeoutMs != 0U ) && ( calculateElapsedTime( now, pContext->lastPacketTxTime ) >= packetTxTimeoutMs ) )
- {
- status = MQTT_Ping( pContext );
- }
- else
- {
- const uint32_t timeElapsed = calculateElapsedTime( now, pContext->lastPacketRxTime );
-
- if( ( timeElapsed != 0U ) && ( timeElapsed >= PACKET_RX_TIMEOUT_MS ) )
- {
- status = MQTT_Ping( pContext );
- }
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t handleIncomingPublish( MQTTContext_t * pContext,
- MQTTPacketInfo_t * pIncomingPacket )
-{
- MQTTStatus_t status = MQTTBadParameter;
- MQTTPublishState_t publishRecordState = MQTTStateNull;
- uint16_t packetIdentifier = 0U;
- MQTTPublishInfo_t publishInfo;
- MQTTDeserializedInfo_t deserializedInfo;
- bool duplicatePublish = false;
-
- assert( pContext != NULL );
- assert( pIncomingPacket != NULL );
- assert( pContext->appCallback != NULL );
-
- status = MQTT_DeserializePublish( pIncomingPacket, &packetIdentifier, &publishInfo );
- LogInfo( ( "De-serialized incoming PUBLISH packet: DeserializerResult=%s.",
- MQTT_Status_strerror( status ) ) );
-
- if( ( status == MQTTSuccess ) &&
- ( pContext->incomingPublishRecords == NULL ) &&
- ( publishInfo.qos > MQTTQoS0 ) )
- {
- LogError( ( "Incoming publish has QoS > MQTTQoS0 but incoming "
- "publish records have not been initialized. Dropping the "
- "incoming publish. Please call MQTT_InitStatefulQoS to enable "
- "use of QoS1 and QoS2 publishes." ) );
- status = MQTTRecvFailed;
- }
-
- if( status == MQTTSuccess )
- {
- MQTT_PRE_STATE_UPDATE_HOOK( pContext );
-
- status = MQTT_UpdateStatePublish( pContext,
- packetIdentifier,
- MQTT_RECEIVE,
- publishInfo.qos,
- &publishRecordState );
-
- MQTT_POST_STATE_UPDATE_HOOK( pContext );
-
- if( status == MQTTSuccess )
- {
- LogInfo( ( "State record updated. New state=%s.",
- MQTT_State_strerror( publishRecordState ) ) );
- }
-
- /* Different cases in which an incoming publish with duplicate flag is
- * handled are as listed below.
- * 1. No collision - This is the first instance of the incoming publish
- * packet received or an earlier received packet state is lost. This
- * will be handled as a new incoming publish for both QoS1 and QoS2
- * publishes.
- * 2. Collision - The incoming packet was received before and a state
- * record is present in the state engine. For QoS1 and QoS2 publishes
- * this case can happen at 2 different cases and handling is
- * different.
- * a. QoS1 - If a PUBACK is not successfully sent for the incoming
- * publish due to a connection issue, it can result in broker
- * sending out a duplicate publish with dup flag set, when a
- * session is reestablished. It can result in a collision in
- * state engine. This will be handled by processing the incoming
- * publish as a new publish ignoring the
- * #MQTTStateCollision status from the state engine. The publish
- * data is not passed to the application.
- * b. QoS2 - If a PUBREC is not successfully sent for the incoming
- * publish or the PUBREC sent is not successfully received by the
- * broker due to a connection issue, it can result in broker
- * sending out a duplicate publish with dup flag set, when a
- * session is reestablished. It can result in a collision in
- * state engine. This will be handled by ignoring the
- * #MQTTStateCollision status from the state engine. The publish
- * data is not passed to the application. */
- else if( status == MQTTStateCollision )
- {
- status = MQTTSuccess;
- duplicatePublish = true;
-
- /* Calculate the state for the ack packet that needs to be sent out
- * for the duplicate incoming publish. */
- publishRecordState = MQTT_CalculateStatePublish( MQTT_RECEIVE,
- publishInfo.qos );
-
- LogDebug( ( "Incoming publish packet with packet id %hu already exists.",
- ( unsigned short ) packetIdentifier ) );
-
- if( publishInfo.dup == false )
- {
- LogError( ( "DUP flag is 0 for duplicate packet (MQTT-3.3.1.-1)." ) );
- }
- }
- else
- {
- LogError( ( "Error in updating publish state for incoming publish with packet id %hu."
- " Error is %s",
- ( unsigned short ) packetIdentifier,
- MQTT_Status_strerror( status ) ) );
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Set fields of deserialized struct. */
- deserializedInfo.packetIdentifier = packetIdentifier;
- deserializedInfo.pPublishInfo = &publishInfo;
- deserializedInfo.deserializationResult = status;
-
- /* Invoke application callback to hand the buffer over to application
- * before sending acks.
- * Application callback will be invoked for all publishes, except for
- * duplicate incoming publishes. */
- if( duplicatePublish == false )
- {
- pContext->appCallback( pContext,
- pIncomingPacket,
- &deserializedInfo );
- }
-
- /* Send PUBACK or PUBREC if necessary. */
- status = sendPublishAcks( pContext,
- packetIdentifier,
- publishRecordState );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t handlePublishAcks( MQTTContext_t * pContext,
- MQTTPacketInfo_t * pIncomingPacket )
-{
- MQTTStatus_t status = MQTTBadResponse;
- MQTTPublishState_t publishRecordState = MQTTStateNull;
- uint16_t packetIdentifier;
- MQTTPubAckType_t ackType;
- MQTTEventCallback_t appCallback;
- MQTTDeserializedInfo_t deserializedInfo;
-
- assert( pContext != NULL );
- assert( pIncomingPacket != NULL );
- assert( pContext->appCallback != NULL );
-
- appCallback = pContext->appCallback;
-
- ackType = getAckFromPacketType( pIncomingPacket->type );
- status = MQTT_DeserializeAck( pIncomingPacket, &packetIdentifier, NULL );
- LogInfo( ( "Ack packet deserialized with result: %s.",
- MQTT_Status_strerror( status ) ) );
-
- if( status == MQTTSuccess )
- {
- MQTT_PRE_STATE_UPDATE_HOOK( pContext );
-
- status = MQTT_UpdateStateAck( pContext,
- packetIdentifier,
- ackType,
- MQTT_RECEIVE,
- &publishRecordState );
-
- MQTT_POST_STATE_UPDATE_HOOK( pContext );
-
- if( status == MQTTSuccess )
- {
- LogInfo( ( "State record updated. New state=%s.",
- MQTT_State_strerror( publishRecordState ) ) );
- }
- else
- {
- LogError( ( "Updating the state engine for packet id %hu"
- " failed with error %s.",
- ( unsigned short ) packetIdentifier,
- MQTT_Status_strerror( status ) ) );
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Set fields of deserialized struct. */
- deserializedInfo.packetIdentifier = packetIdentifier;
- deserializedInfo.deserializationResult = status;
- deserializedInfo.pPublishInfo = NULL;
-
- /* Invoke application callback to hand the buffer over to application
- * before sending acks. */
- appCallback( pContext, pIncomingPacket, &deserializedInfo );
-
- /* Send PUBREL or PUBCOMP if necessary. */
- status = sendPublishAcks( pContext,
- packetIdentifier,
- publishRecordState );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t handleIncomingAck( MQTTContext_t * pContext,
- MQTTPacketInfo_t * pIncomingPacket,
- bool manageKeepAlive )
-{
- MQTTStatus_t status = MQTTBadResponse;
- uint16_t packetIdentifier = MQTT_PACKET_ID_INVALID;
- MQTTDeserializedInfo_t deserializedInfo;
-
- /* We should always invoke the app callback unless we receive a PINGRESP
- * and are managing keep alive, or if we receive an unknown packet. We
- * initialize this to false since the callback must be invoked before
- * sending any PUBREL or PUBCOMP. However, for other cases, we invoke it
- * at the end to reduce the complexity of this function. */
- bool invokeAppCallback = false;
- MQTTEventCallback_t appCallback = NULL;
-
- assert( pContext != NULL );
- assert( pIncomingPacket != NULL );
- assert( pContext->appCallback != NULL );
-
- appCallback = pContext->appCallback;
-
- LogDebug( ( "Received packet of type %02x.",
- ( unsigned int ) pIncomingPacket->type ) );
-
- switch( pIncomingPacket->type )
- {
- case MQTT_PACKET_TYPE_PUBACK:
- case MQTT_PACKET_TYPE_PUBREC:
- case MQTT_PACKET_TYPE_PUBREL:
- case MQTT_PACKET_TYPE_PUBCOMP:
-
- /* Handle all the publish acks. The app callback is invoked here. */
- status = handlePublishAcks( pContext, pIncomingPacket );
-
- break;
-
- case MQTT_PACKET_TYPE_PINGRESP:
- status = MQTT_DeserializeAck( pIncomingPacket, &packetIdentifier, NULL );
- invokeAppCallback = ( status == MQTTSuccess ) && !manageKeepAlive;
-
- if( ( status == MQTTSuccess ) && ( manageKeepAlive == true ) )
- {
- pContext->waitingForPingResp = false;
- }
-
- break;
-
- case MQTT_PACKET_TYPE_SUBACK:
- case MQTT_PACKET_TYPE_UNSUBACK:
- /* Deserialize and give these to the app provided callback. */
- status = MQTT_DeserializeAck( pIncomingPacket, &packetIdentifier, NULL );
- invokeAppCallback = ( status == MQTTSuccess ) || ( status == MQTTServerRefused );
- break;
-
- default:
- /* Bad response from the server. */
- LogError( ( "Unexpected packet type from server: PacketType=%02x.",
- ( unsigned int ) pIncomingPacket->type ) );
- status = MQTTBadResponse;
- break;
- }
-
- if( invokeAppCallback == true )
- {
- /* Set fields of deserialized struct. */
- deserializedInfo.packetIdentifier = packetIdentifier;
- deserializedInfo.deserializationResult = status;
- deserializedInfo.pPublishInfo = NULL;
- appCallback( pContext, pIncomingPacket, &deserializedInfo );
- /* In case a SUBACK indicated refusal, reset the status to continue the loop. */
- status = MQTTSuccess;
- }
-
- return status;
-}
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t receiveSingleIteration( MQTTContext_t * pContext,
- bool manageKeepAlive )
-{
- MQTTStatus_t status = MQTTSuccess;
- MQTTPacketInfo_t incomingPacket = { 0 };
- int32_t recvBytes;
- size_t totalMQTTPacketLength = 0;
-
- assert( pContext != NULL );
- assert( pContext->networkBuffer.pBuffer != NULL );
-
- /* Read as many bytes as possible into the network buffer. */
- recvBytes = pContext->transportInterface.recv( pContext->transportInterface.pNetworkContext,
- &( pContext->networkBuffer.pBuffer[ pContext->index ] ),
- pContext->networkBuffer.size - pContext->index );
-
- if( recvBytes < 0 )
- {
- /* The receive function has failed. Bubble up the error up to the user. */
- status = MQTTRecvFailed;
- }
- else if( ( recvBytes == 0 ) && ( pContext->index == 0U ) )
- {
- /* No more bytes available since the last read and neither is anything in
- * the buffer. */
- status = MQTTNoDataAvailable;
- }
-
- /* Either something was received, or there is still data to be processed in the
- * buffer, or both. */
- else
- {
- /* Update the number of bytes in the MQTT fixed buffer. */
- pContext->index += ( size_t ) recvBytes;
-
- status = MQTT_ProcessIncomingPacketTypeAndLength( pContext->networkBuffer.pBuffer,
- &pContext->index,
- &incomingPacket );
-
- totalMQTTPacketLength = incomingPacket.remainingLength + incomingPacket.headerLength;
- }
-
- /* No data was received, check for keep alive timeout. */
- if( recvBytes == 0 )
- {
- if( manageKeepAlive == true )
- {
- /* Keep the copy of the status to be reset later. */
- MQTTStatus_t statusCopy = status;
-
- /* Assign status so an error can be bubbled up to application,
- * but reset it on success. */
- status = handleKeepAlive( pContext );
-
- if( status == MQTTSuccess )
- {
- /* Reset the status. */
- status = statusCopy;
- }
- else
- {
- LogError( ( "Handling of keep alive failed. Status=%s",
- MQTT_Status_strerror( status ) ) );
- }
- }
- }
-
- /* Check whether there is data available before processing the packet further. */
- if( ( status == MQTTNeedMoreBytes ) || ( status == MQTTNoDataAvailable ) )
- {
- /* Do nothing as there is nothing to be processed right now. The proper
- * error code will be bubbled up to the user. */
- }
- /* Any other error code. */
- else if( status != MQTTSuccess )
- {
- LogError( ( "Call to receiveSingleIteration failed. Status=%s",
- MQTT_Status_strerror( status ) ) );
- }
- /* If the MQTT Packet size is bigger than the buffer itself. */
- else if( totalMQTTPacketLength > pContext->networkBuffer.size )
- {
- /* Discard the packet from the receive buffer and drain the pending
- * data from the socket buffer. */
- status = discardStoredPacket( pContext,
- &incomingPacket );
- }
- /* If the total packet is of more length than the bytes we have available. */
- else if( totalMQTTPacketLength > pContext->index )
- {
- status = MQTTNeedMoreBytes;
- }
- else
- {
- /* MISRA else. */
- }
-
- /* Handle received packet. If incomplete data was read then this will not execute. */
- if( status == MQTTSuccess )
- {
- incomingPacket.pRemainingData = &pContext->networkBuffer.pBuffer[ incomingPacket.headerLength ];
-
- /* PUBLISH packets allow flags in the lower four bits. For other
- * packet types, they are reserved. */
- if( ( incomingPacket.type & 0xF0U ) == MQTT_PACKET_TYPE_PUBLISH )
- {
- status = handleIncomingPublish( pContext, &incomingPacket );
- }
- else
- {
- status = handleIncomingAck( pContext, &incomingPacket, manageKeepAlive );
- }
-
- /* Update the index to reflect the remaining bytes in the buffer. */
- pContext->index -= totalMQTTPacketLength;
-
- /* Move the remaining bytes to the front of the buffer. */
- ( void ) memmove( pContext->networkBuffer.pBuffer,
- &( pContext->networkBuffer.pBuffer[ totalMQTTPacketLength ] ),
- pContext->index );
- }
-
- if( status == MQTTNoDataAvailable )
- {
- /* No data available is not an error. Reset to MQTTSuccess so the
- * return code will indicate success. */
- status = MQTTSuccess;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t validateSubscribeUnsubscribeParams( const MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t iterator;
-
- /* Validate all the parameters. */
- if( ( pContext == NULL ) || ( pSubscriptionList == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pContext=%p, "
- "pSubscriptionList=%p.",
- ( void * ) pContext,
- ( void * ) pSubscriptionList ) );
- status = MQTTBadParameter;
- }
- else if( subscriptionCount == 0UL )
- {
- LogError( ( "Subscription count is 0." ) );
- status = MQTTBadParameter;
- }
- else if( packetId == 0U )
- {
- LogError( ( "Packet Id for subscription packet is 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- if( pContext->incomingPublishRecords == NULL )
- {
- for( iterator = 0; iterator < subscriptionCount; iterator++ )
- {
- if( pSubscriptionList->qos > MQTTQoS0 )
- {
- LogError( ( "The incoming publish record list is not "
- "initialised for QoS1/QoS2 records. Please call "
- " MQTT_InitStatefulQoS to enable use of QoS1 and "
- " QoS2 packets." ) );
- status = MQTTBadParameter;
- break;
- }
- }
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static size_t addEncodedStringToVector( uint8_t serailizedLength[ 2 ],
- const char * const string,
- uint16_t length,
- TransportOutVector_t * iterator,
- size_t * updatedLength )
-{
- size_t packetLength = 0U;
- const size_t seralizedLengthFieldSize = 2U;
- TransportOutVector_t * pLocalIterator = iterator;
- /* This function always adds 2 vectors. */
- size_t vectorsAdded = 0U;
-
- /* When length is non-zero, the string must be non-NULL. */
- assert( ( length != 0U ) == ( string != NULL ) );
-
- serailizedLength[ 0 ] = ( ( uint8_t ) ( ( length ) >> 8 ) );
- serailizedLength[ 1 ] = ( ( uint8_t ) ( ( length ) & 0x00ffU ) );
-
- /* Add the serialized length of the string first. */
- pLocalIterator[ 0 ].iov_base = serailizedLength;
- pLocalIterator[ 0 ].iov_len = seralizedLengthFieldSize;
- vectorsAdded++;
- packetLength = seralizedLengthFieldSize;
-
- /* Sometimes the string can be NULL that is, of 0 length. In that case,
- * only the length field should be encoded in the vector. */
- if( ( string != NULL ) && ( length != 0U ) )
- {
- /* Then add the pointer to the string itself. */
- pLocalIterator[ 1 ].iov_base = string;
- pLocalIterator[ 1 ].iov_len = length;
- vectorsAdded++;
- packetLength += length;
- }
-
- ( *updatedLength ) = ( *updatedLength ) + packetLength;
-
- return vectorsAdded;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t sendSubscribeWithoutCopy( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength )
-{
- MQTTStatus_t status = MQTTSuccess;
- uint8_t subscribeheader[ 7 ];
- uint8_t * pIndex;
- TransportOutVector_t pIoVector[ MQTT_SUB_UNSUB_MAX_VECTORS ];
- TransportOutVector_t * pIterator;
- uint8_t serializedTopicFieldLength[ MQTT_SUB_UNSUB_MAX_VECTORS ][ 2 ];
- size_t totalPacketLength = 0U;
- size_t ioVectorLength = 0U;
- size_t subscriptionsSent = 0U;
- /* For subscribe, only three vector slots are required per topic string. */
- const size_t subscriptionStringVectorSlots = 3U;
- size_t vectorsAdded;
- size_t topicFieldLengthIndex;
-
- /* The vector array should be at least three element long as the topic
- * string needs these many vector elements to be stored. */
- assert( MQTT_SUB_UNSUB_MAX_VECTORS >= subscriptionStringVectorSlots );
-
- pIndex = subscribeheader;
- pIterator = pIoVector;
-
- pIndex = MQTT_SerializeSubscribeHeader( remainingLength,
- pIndex,
- packetId );
-
- /* The header is to be sent first. */
- pIterator->iov_base = subscribeheader;
- /* More details at: https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-182 */
- /* More details at: https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-108 */
- /* coverity[misra_c_2012_rule_18_2_violation] */
- /* coverity[misra_c_2012_rule_10_8_violation] */
- pIterator->iov_len = ( size_t ) ( pIndex - subscribeheader );
- totalPacketLength += pIterator->iov_len;
- pIterator++;
- ioVectorLength++;
-
- while( ( status == MQTTSuccess ) && ( subscriptionsSent < subscriptionCount ) )
- {
- /* Reset the index for next iteration. */
- topicFieldLengthIndex = 0;
-
- /* Check whether the subscription topic (with QoS) will fit in the
- * given vector. */
- while( ( ioVectorLength <= ( MQTT_SUB_UNSUB_MAX_VECTORS - subscriptionStringVectorSlots ) ) &&
- ( subscriptionsSent < subscriptionCount ) )
- {
- /* The topic filter gets sent next. */
- vectorsAdded = addEncodedStringToVector( serializedTopicFieldLength[ topicFieldLengthIndex ],
- pSubscriptionList[ subscriptionsSent ].pTopicFilter,
- pSubscriptionList[ subscriptionsSent ].topicFilterLength,
- pIterator,
- &totalPacketLength );
-
- /* Update the pointer after the above operation. */
- pIterator = &pIterator[ vectorsAdded ];
-
- /* Lastly, the QoS gets sent. */
- pIterator->iov_base = &( pSubscriptionList[ subscriptionsSent ].qos );
- pIterator->iov_len = 1U;
- totalPacketLength += pIterator->iov_len;
-
- /* Increment the pointer. */
- pIterator++;
-
- /* Two slots get used by the topic string length and topic string.
- * One slot gets used by the quality of service. */
- ioVectorLength += vectorsAdded + 1U;
-
- subscriptionsSent++;
-
- /* The index needs to be updated for next iteration. */
- topicFieldLengthIndex++;
- }
-
- if( sendMessageVector( pContext,
- pIoVector,
- ioVectorLength ) != ( int32_t ) totalPacketLength )
- {
- status = MQTTSendFailed;
- }
-
- /* Update the iterator for the next potential loop iteration. */
- pIterator = pIoVector;
- /* Reset the vector length for the next potential loop iteration. */
- ioVectorLength = 0U;
- /* Reset the packet length for the next potential loop iteration. */
- totalPacketLength = 0U;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t sendUnsubscribeWithoutCopy( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength )
-{
- MQTTStatus_t status = MQTTSuccess;
- uint8_t unsubscribeheader[ 7 ];
- uint8_t * pIndex;
- TransportOutVector_t pIoVector[ MQTT_SUB_UNSUB_MAX_VECTORS ];
- TransportOutVector_t * pIterator;
- uint8_t serializedTopicFieldLength[ MQTT_SUB_UNSUB_MAX_VECTORS ][ 2 ];
- size_t totalPacketLength = 0U;
- size_t unsubscriptionsSent = 0U;
- size_t ioVectorLength = 0U;
- /* For unsubscribe, only two vector slots are required per topic string. */
- const size_t unsubscribeStringVectorSlots = 2U;
- size_t vectorsAdded;
- size_t topicFieldLengthIndex;
-
- /* The vector array should be at least three element long as the topic
- * string needs these many vector elements to be stored. */
- assert( MQTT_SUB_UNSUB_MAX_VECTORS >= unsubscribeStringVectorSlots );
-
- pIndex = unsubscribeheader;
- pIterator = pIoVector;
-
- pIndex = MQTT_SerializeUnsubscribeHeader( remainingLength,
- pIndex,
- packetId );
-
- /* The header is to be sent first. */
- pIterator->iov_base = unsubscribeheader;
- /* More details at: https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-182 */
- /* More details at: https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-108 */
- /* coverity[misra_c_2012_rule_18_2_violation] */
- /* coverity[misra_c_2012_rule_10_8_violation] */
- pIterator->iov_len = ( size_t ) ( pIndex - unsubscribeheader );
- totalPacketLength += pIterator->iov_len;
- pIterator++;
- ioVectorLength++;
-
- while( ( status == MQTTSuccess ) && ( unsubscriptionsSent < subscriptionCount ) )
- {
- /* Reset the index for next iteration. */
- topicFieldLengthIndex = 0;
-
- /* Check whether the subscription topic will fit in the given vector. */
- while( ( ioVectorLength <= ( MQTT_SUB_UNSUB_MAX_VECTORS - unsubscribeStringVectorSlots ) ) &&
- ( unsubscriptionsSent < subscriptionCount ) )
- {
- /* The topic filter gets sent next. */
- vectorsAdded = addEncodedStringToVector( serializedTopicFieldLength[ topicFieldLengthIndex ],
- pSubscriptionList[ unsubscriptionsSent ].pTopicFilter,
- pSubscriptionList[ unsubscriptionsSent ].topicFilterLength,
- pIterator,
- &totalPacketLength );
-
- /* Update the iterator to point to the next empty location. */
- pIterator = &pIterator[ vectorsAdded ];
- /* Update the total count based on how many vectors were added. */
- ioVectorLength += vectorsAdded;
-
- unsubscriptionsSent++;
-
- /* Update the index for next iteration. */
- topicFieldLengthIndex++;
- }
-
- if( sendMessageVector( pContext, pIoVector, ioVectorLength ) != ( int32_t ) totalPacketLength )
- {
- status = MQTTSendFailed;
- }
-
- /* Update the iterator for the next potential loop iteration. */
- pIterator = pIoVector;
- /* Reset the vector length for the next potential loop iteration. */
- ioVectorLength = 0U;
- /* Reset the packet length for the next potential loop iteration. */
- totalPacketLength = 0U;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t sendPublishWithoutCopy( MQTTContext_t * pContext,
- const MQTTPublishInfo_t * pPublishInfo,
- const uint8_t * pMqttHeader,
- size_t headerSize,
- uint16_t packetId )
-{
- MQTTStatus_t status = MQTTSuccess;
- uint8_t serializedPacketID[ 2 ];
- TransportOutVector_t pIoVector[ 4 ];
- size_t ioVectorLength;
- size_t totalMessageLength;
- const size_t packetIDLength = 2U;
-
- /* The header is sent first. */
- pIoVector[ 0U ].iov_base = pMqttHeader;
- pIoVector[ 0U ].iov_len = headerSize;
- totalMessageLength = headerSize;
-
- /* Then the topic name has to be sent. */
- pIoVector[ 1U ].iov_base = pPublishInfo->pTopicName;
- pIoVector[ 1U ].iov_len = pPublishInfo->topicNameLength;
- totalMessageLength += pPublishInfo->topicNameLength;
-
- /* The next field's index should be 2 as the first two fields
- * have been filled in. */
- ioVectorLength = 2U;
-
- if( pPublishInfo->qos > MQTTQoS0 )
- {
- /* Encode the packet ID. */
- serializedPacketID[ 0 ] = ( ( uint8_t ) ( ( packetId ) >> 8 ) );
- serializedPacketID[ 1 ] = ( ( uint8_t ) ( ( packetId ) & 0x00ffU ) );
-
- pIoVector[ ioVectorLength ].iov_base = serializedPacketID;
- pIoVector[ ioVectorLength ].iov_len = packetIDLength;
-
- ioVectorLength++;
- totalMessageLength += packetIDLength;
- }
-
- /* Publish packets are allowed to contain no payload. */
- if( pPublishInfo->payloadLength > 0U )
- {
- pIoVector[ ioVectorLength ].iov_base = pPublishInfo->pPayload;
- pIoVector[ ioVectorLength ].iov_len = pPublishInfo->payloadLength;
-
- ioVectorLength++;
- totalMessageLength += pPublishInfo->payloadLength;
- }
-
- if( sendMessageVector( pContext, pIoVector, ioVectorLength ) != ( int32_t ) totalMessageLength )
- {
- status = MQTTSendFailed;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t sendConnectWithoutCopy( MQTTContext_t * pContext,
- const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength )
-{
- MQTTStatus_t status = MQTTSuccess;
- TransportOutVector_t * iterator;
- size_t ioVectorLength = 0U;
- size_t totalMessageLength = 0U;
- int32_t bytesSentOrError;
-
- /* Connect packet header can be of maximum 15 bytes. */
- uint8_t connectPacketHeader[ 15 ];
- uint8_t * pIndex = connectPacketHeader;
- TransportOutVector_t pIoVector[ 11 ];
- uint8_t serializedClientIDLength[ 2 ];
- uint8_t serializedTopicLength[ 2 ];
- uint8_t serializedPayloadLength[ 2 ];
- uint8_t serializedUsernameLength[ 2 ];
- uint8_t serializedPasswordLength[ 2 ];
- size_t vectorsAdded;
-
- iterator = pIoVector;
-
- /* Validate arguments. */
- if( ( pWillInfo != NULL ) && ( pWillInfo->pTopicName == NULL ) )
- {
- LogError( ( "pWillInfo->pTopicName cannot be NULL if Will is present." ) );
- status = MQTTBadParameter;
- }
- else
- {
- pIndex = MQTT_SerializeConnectFixedHeader( pIndex,
- pConnectInfo,
- pWillInfo,
- remainingLength );
-
- assert( ( pIndex - connectPacketHeader ) <= 15 );
-
- /* The header gets sent first. */
- iterator->iov_base = connectPacketHeader;
- /* More details at: https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-182 */
- /* More details at: https://github.com/FreeRTOS/coreMQTT/blob/main/MISRA.md#rule-108 */
- /* coverity[misra_c_2012_rule_18_2_violation] */
- /* coverity[misra_c_2012_rule_10_8_violation] */
- iterator->iov_len = ( size_t ) ( pIndex - connectPacketHeader );
- totalMessageLength += iterator->iov_len;
- iterator++;
- ioVectorLength++;
-
- /* Serialize the client ID. */
- vectorsAdded = addEncodedStringToVector( serializedClientIDLength,
- pConnectInfo->pClientIdentifier,
- pConnectInfo->clientIdentifierLength,
- iterator,
- &totalMessageLength );
-
- /* Update the iterator to point to the next empty slot. */
- iterator = &iterator[ vectorsAdded ];
- ioVectorLength += vectorsAdded;
-
- if( pWillInfo != NULL )
- {
- /* Serialize the topic. */
- vectorsAdded = addEncodedStringToVector( serializedTopicLength,
- pWillInfo->pTopicName,
- pWillInfo->topicNameLength,
- iterator,
- &totalMessageLength );
-
- /* Update the iterator to point to the next empty slot. */
- iterator = &iterator[ vectorsAdded ];
- ioVectorLength += vectorsAdded;
-
-
- /* Serialize the payload. Payload of last will and testament can be NULL. */
- vectorsAdded = addEncodedStringToVector( serializedPayloadLength,
- pWillInfo->pPayload,
- ( uint16_t ) pWillInfo->payloadLength,
- iterator,
- &totalMessageLength );
-
- /* Update the iterator to point to the next empty slot. */
- iterator = &iterator[ vectorsAdded ];
- ioVectorLength += vectorsAdded;
- }
-
- /* Encode the user name if provided. */
- if( pConnectInfo->pUserName != NULL )
- {
- /* Serialize the user name string. */
- vectorsAdded = addEncodedStringToVector( serializedUsernameLength,
- pConnectInfo->pUserName,
- pConnectInfo->userNameLength,
- iterator,
- &totalMessageLength );
-
- /* Update the iterator to point to the next empty slot. */
- iterator = &iterator[ vectorsAdded ];
- ioVectorLength += vectorsAdded;
- }
-
- /* Encode the password if provided. */
- if( pConnectInfo->pPassword != NULL )
- {
- /* Serialize the user name string. */
- vectorsAdded = addEncodedStringToVector( serializedPasswordLength,
- pConnectInfo->pPassword,
- pConnectInfo->passwordLength,
- iterator,
- &totalMessageLength );
- /* Update the iterator to point to the next empty slot. */
- iterator = &iterator[ vectorsAdded ];
- ioVectorLength += vectorsAdded;
- }
-
- bytesSentOrError = sendMessageVector( pContext, pIoVector, ioVectorLength );
-
- if( bytesSentOrError != ( int32_t ) totalMessageLength )
- {
- status = MQTTSendFailed;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t receiveConnack( const MQTTContext_t * pContext,
- uint32_t timeoutMs,
- bool cleanSession,
- MQTTPacketInfo_t * pIncomingPacket,
- bool * pSessionPresent )
-{
- MQTTStatus_t status = MQTTSuccess;
- MQTTGetCurrentTimeFunc_t getTimeStamp = NULL;
- uint32_t entryTimeMs = 0U, remainingTimeMs = 0U, timeTakenMs = 0U;
- bool breakFromLoop = false;
- uint16_t loopCount = 0U;
-
- assert( pContext != NULL );
- assert( pIncomingPacket != NULL );
- assert( pContext->getTime != NULL );
-
- getTimeStamp = pContext->getTime;
-
- /* Get the entry time for the function. */
- entryTimeMs = getTimeStamp();
-
- do
- {
- /* Transport read for incoming CONNACK packet type and length.
- * MQTT_GetIncomingPacketTypeAndLength is a blocking call and it is
- * returned after a transport receive timeout, an error, or a successful
- * receive of packet type and length. */
- status = MQTT_GetIncomingPacketTypeAndLength( pContext->transportInterface.recv,
- pContext->transportInterface.pNetworkContext,
- pIncomingPacket );
-
- /* The loop times out based on 2 conditions.
- * 1. If timeoutMs is greater than 0:
- * Loop times out based on the timeout calculated by getTime()
- * function.
- * 2. If timeoutMs is 0:
- * Loop times out based on the maximum number of retries config
- * MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT. This config will control
- * maximum the number of retry attempts to read the CONNACK packet.
- * A value of 0 for the config will try once to read CONNACK. */
- if( timeoutMs > 0U )
- {
- breakFromLoop = calculateElapsedTime( getTimeStamp(), entryTimeMs ) >= timeoutMs;
- }
- else
- {
- breakFromLoop = loopCount >= MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT;
- loopCount++;
- }
-
- /* Loop until there is data to read or if we have exceeded the timeout/retries. */
- } while( ( status == MQTTNoDataAvailable ) && ( breakFromLoop == false ) );
-
- if( status == MQTTSuccess )
- {
- /* Time taken in this function so far. */
- timeTakenMs = calculateElapsedTime( getTimeStamp(), entryTimeMs );
-
- if( timeTakenMs < timeoutMs )
- {
- /* Calculate remaining time for receiving the remainder of
- * the packet. */
- remainingTimeMs = timeoutMs - timeTakenMs;
- }
-
- /* Reading the remainder of the packet by transport recv.
- * Attempt to read once even if the timeout has expired.
- * Invoking receivePacket with remainingTime as 0 would attempt to
- * recv from network once. If using retries, the remainder of the
- * CONNACK packet is tried to be read only once. Reading once would be
- * good as the packet type and remaining length was already read. Hence,
- * the probability of the remaining 2 bytes available to read is very high. */
- if( pIncomingPacket->type == MQTT_PACKET_TYPE_CONNACK )
- {
- status = receivePacket( pContext,
- *pIncomingPacket,
- remainingTimeMs );
- }
- else
- {
- LogError( ( "Incorrect packet type %X received while expecting"
- " CONNACK(%X).",
- ( unsigned int ) pIncomingPacket->type,
- MQTT_PACKET_TYPE_CONNACK ) );
- status = MQTTBadResponse;
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Update the packet info pointer to the buffer read. */
- pIncomingPacket->pRemainingData = pContext->networkBuffer.pBuffer;
-
- /* Deserialize CONNACK. */
- status = MQTT_DeserializeAck( pIncomingPacket, NULL, pSessionPresent );
- }
-
- /* If a clean session is requested, a session present should not be set by
- * broker. */
- if( status == MQTTSuccess )
- {
- if( ( cleanSession == true ) && ( *pSessionPresent == true ) )
- {
- LogError( ( "Unexpected session present flag in CONNACK response from broker."
- " CONNECT request with clean session was made with broker." ) );
- status = MQTTBadResponse;
- }
- }
-
- if( status == MQTTSuccess )
- {
- LogDebug( ( "Received MQTT CONNACK successfully from broker." ) );
- }
- else
- {
- LogError( ( "CONNACK recv failed with status = %s.",
- MQTT_Status_strerror( status ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t handleSessionResumption( MQTTContext_t * pContext,
- bool sessionPresent )
-{
- MQTTStatus_t status = MQTTSuccess;
- MQTTStateCursor_t cursor = MQTT_STATE_CURSOR_INITIALIZER;
- uint16_t packetId = MQTT_PACKET_ID_INVALID;
- MQTTPublishState_t state = MQTTStateNull;
-
- assert( pContext != NULL );
-
- /* Reset the index and clear the buffer when a new session is established. */
- pContext->index = 0;
- ( void ) memset( pContext->networkBuffer.pBuffer, 0, pContext->networkBuffer.size );
-
- if( sessionPresent == true )
- {
- /* Get the next packet ID for which a PUBREL need to be resent. */
- packetId = MQTT_PubrelToResend( pContext, &cursor, &state );
-
- /* Resend all the PUBREL acks after session is reestablished. */
- while( ( packetId != MQTT_PACKET_ID_INVALID ) &&
- ( status == MQTTSuccess ) )
- {
- status = sendPublishAcks( pContext, packetId, state );
-
- packetId = MQTT_PubrelToResend( pContext, &cursor, &state );
- }
- }
- else
- {
- /* Clear any existing records if a new session is established. */
- if( pContext->outgoingPublishRecordMaxCount > 0U )
- {
- ( void ) memset( pContext->outgoingPublishRecords,
- 0x00,
- pContext->outgoingPublishRecordMaxCount * sizeof( *pContext->outgoingPublishRecords ) );
- }
-
- if( pContext->incomingPublishRecordMaxCount > 0U )
- {
- ( void ) memset( pContext->incomingPublishRecords,
- 0x00,
- pContext->incomingPublishRecordMaxCount * sizeof( *pContext->incomingPublishRecords ) );
- }
- }
-
- return status;
-}
-
-static MQTTStatus_t validatePublishParams( const MQTTContext_t * pContext,
- const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- /* Validate arguments. */
- if( ( pContext == NULL ) || ( pPublishInfo == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pContext=%p, "
- "pPublishInfo=%p.",
- ( void * ) pContext,
- ( void * ) pPublishInfo ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->qos != MQTTQoS0 ) && ( packetId == 0U ) )
- {
- LogError( ( "Packet Id is 0 for PUBLISH with QoS=%u.",
- ( unsigned int ) pPublishInfo->qos ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->payloadLength > 0U ) && ( pPublishInfo->pPayload == NULL ) )
- {
- LogError( ( "A nonzero payload length requires a non-NULL payload: "
- "payloadLength=%lu, pPayload=%p.",
- ( unsigned long ) pPublishInfo->payloadLength,
- pPublishInfo->pPayload ) );
- status = MQTTBadParameter;
- }
- else if( ( pContext->outgoingPublishRecords == NULL ) && ( pPublishInfo->qos > MQTTQoS0 ) )
- {
- LogError( ( "Trying to publish a QoS > MQTTQoS0 packet when outgoing publishes "
- "for QoS1/QoS2 have not been enabled. Please, call MQTT_InitStatefulQoS "
- "to initialize and enable the use of QoS1/QoS2 publishes." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* MISRA else */
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Init( MQTTContext_t * pContext,
- const TransportInterface_t * pTransportInterface,
- MQTTGetCurrentTimeFunc_t getTimeFunction,
- MQTTEventCallback_t userCallback,
- const MQTTFixedBuffer_t * pNetworkBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- /* Validate arguments. */
- if( ( pContext == NULL ) || ( pTransportInterface == NULL ) ||
- ( pNetworkBuffer == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pContext=%p, "
- "pTransportInterface=%p, "
- "pNetworkBuffer=%p",
- ( void * ) pContext,
- ( void * ) pTransportInterface,
- ( void * ) pNetworkBuffer ) );
- status = MQTTBadParameter;
- }
- else if( getTimeFunction == NULL )
- {
- LogError( ( "Invalid parameter: getTimeFunction is NULL" ) );
- status = MQTTBadParameter;
- }
- else if( userCallback == NULL )
- {
- LogError( ( "Invalid parameter: userCallback is NULL" ) );
- status = MQTTBadParameter;
- }
- else if( pTransportInterface->recv == NULL )
- {
- LogError( ( "Invalid parameter: pTransportInterface->recv is NULL" ) );
- status = MQTTBadParameter;
- }
- else if( pTransportInterface->send == NULL )
- {
- LogError( ( "Invalid parameter: pTransportInterface->send is NULL" ) );
- status = MQTTBadParameter;
- }
- else
- {
- ( void ) memset( pContext, 0x00, sizeof( MQTTContext_t ) );
-
- pContext->connectStatus = MQTTNotConnected;
- pContext->transportInterface = *pTransportInterface;
- pContext->getTime = getTimeFunction;
- pContext->appCallback = userCallback;
- pContext->networkBuffer = *pNetworkBuffer;
-
- /* Zero is not a valid packet ID per MQTT spec. Start from 1. */
- pContext->nextPacketId = 1;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_InitStatefulQoS( MQTTContext_t * pContext,
- MQTTPubAckInfo_t * pOutgoingPublishRecords,
- size_t outgoingPublishCount,
- MQTTPubAckInfo_t * pIncomingPublishRecords,
- size_t incomingPublishCount )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pContext == NULL )
- {
- LogError( ( "Argument cannot be NULL: pContext=%p\n",
- ( void * ) pContext ) );
- status = MQTTBadParameter;
- }
-
- /* Check whether the arguments make sense. Not equal here behaves
- * like an exclusive-or operator for boolean values. */
- else if( ( outgoingPublishCount == 0U ) !=
- ( pOutgoingPublishRecords == NULL ) )
- {
- LogError( ( "Arguments do not match: pOutgoingPublishRecords=%p, "
- "outgoingPublishCount=%lu",
- ( void * ) pOutgoingPublishRecords,
- outgoingPublishCount ) );
- status = MQTTBadParameter;
- }
-
- /* Check whether the arguments make sense. Not equal here behaves
- * like an exclusive-or operator for boolean values. */
- else if( ( incomingPublishCount == 0U ) !=
- ( pIncomingPublishRecords == NULL ) )
- {
- LogError( ( "Arguments do not match: pIncomingPublishRecords=%p, "
- "incomingPublishCount=%lu",
- ( void * ) pIncomingPublishRecords,
- incomingPublishCount ) );
- status = MQTTBadParameter;
- }
- else if( pContext->appCallback == NULL )
- {
- LogError( ( "MQTT_InitStatefulQoS must be called only after MQTT_Init has"
- " been called succesfully.\n" ) );
- status = MQTTBadParameter;
- }
- else
- {
- pContext->incomingPublishRecordMaxCount = incomingPublishCount;
- pContext->incomingPublishRecords = pIncomingPublishRecords;
- pContext->outgoingPublishRecordMaxCount = outgoingPublishCount;
- pContext->outgoingPublishRecords = pOutgoingPublishRecords;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_CancelCallback( const MQTTContext_t * pContext,
- uint16_t packetId )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pContext == NULL )
- {
- LogWarn( ( "pContext is NULL\n" ) );
- status = MQTTBadParameter;
- }
- else if( pContext->outgoingPublishRecords == NULL )
- {
- LogError( ( "QoS1/QoS2 is not initialized for use. Please, "
- "call MQTT_InitStatefulQoS to enable QoS1 and QoS2 "
- "publishes.\n" ) );
- status = MQTTBadParameter;
- }
- else
- {
- MQTT_PRE_STATE_UPDATE_HOOK( pContext );
-
- status = MQTT_RemoveStateRecord( pContext,
- packetId );
-
- MQTT_POST_STATE_UPDATE_HOOK( pContext );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Connect( MQTTContext_t * pContext,
- const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- uint32_t timeoutMs,
- bool * pSessionPresent )
-{
- size_t remainingLength = 0UL, packetSize = 0UL;
- MQTTStatus_t status = MQTTSuccess;
- MQTTPacketInfo_t incomingPacket = { 0 };
-
- incomingPacket.type = ( uint8_t ) 0;
-
- if( ( pContext == NULL ) || ( pConnectInfo == NULL ) || ( pSessionPresent == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pContext=%p, "
- "pConnectInfo=%p, pSessionPresent=%p.",
- ( void * ) pContext,
- ( void * ) pConnectInfo,
- ( void * ) pSessionPresent ) );
- status = MQTTBadParameter;
- }
-
- if( status == MQTTSuccess )
- {
- /* Get MQTT connect packet size and remaining length. */
- status = MQTT_GetConnectPacketSize( pConnectInfo,
- pWillInfo,
- &remainingLength,
- &packetSize );
- LogDebug( ( "CONNECT packet size is %lu and remaining length is %lu.",
- ( unsigned long ) packetSize,
- ( unsigned long ) remainingLength ) );
- }
-
- if( status == MQTTSuccess )
- {
- MQTT_PRE_SEND_HOOK( pContext );
-
- status = sendConnectWithoutCopy( pContext,
- pConnectInfo,
- pWillInfo,
- remainingLength );
-
- MQTT_POST_SEND_HOOK( pContext );
- }
-
- /* Read CONNACK from transport layer. */
- if( status == MQTTSuccess )
- {
- status = receiveConnack( pContext,
- timeoutMs,
- pConnectInfo->cleanSession,
- &incomingPacket,
- pSessionPresent );
- }
-
- if( status == MQTTSuccess )
- {
- /* Resend PUBRELs when reestablishing a session, or clear records for new sessions. */
- status = handleSessionResumption( pContext, *pSessionPresent );
- }
-
- if( status == MQTTSuccess )
- {
- LogInfo( ( "MQTT connection established with the broker." ) );
- pContext->connectStatus = MQTTConnected;
- /* Initialize keep-alive fields after a successful connection. */
- pContext->keepAliveIntervalSec = pConnectInfo->keepAliveSeconds;
- pContext->waitingForPingResp = false;
- pContext->pingReqSendTimeMs = 0U;
- }
- else
- {
- LogError( ( "MQTT connection failed with status = %s.",
- MQTT_Status_strerror( status ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Subscribe( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId )
-{
- size_t remainingLength = 0UL, packetSize = 0UL;
-
- /* Validate arguments. */
- MQTTStatus_t status = validateSubscribeUnsubscribeParams( pContext,
- pSubscriptionList,
- subscriptionCount,
- packetId );
-
- if( status == MQTTSuccess )
- {
- /* Get the remaining length and packet size.*/
- status = MQTT_GetSubscribePacketSize( pSubscriptionList,
- subscriptionCount,
- &remainingLength,
- &packetSize );
- LogDebug( ( "SUBSCRIBE packet size is %lu and remaining length is %lu.",
- ( unsigned long ) packetSize,
- ( unsigned long ) remainingLength ) );
- }
-
- if( status == MQTTSuccess )
- {
- MQTT_PRE_SEND_HOOK( pContext );
-
- /* Send MQTT SUBSCRIBE packet. */
- status = sendSubscribeWithoutCopy( pContext,
- pSubscriptionList,
- subscriptionCount,
- packetId,
- remainingLength );
-
- MQTT_POST_SEND_HOOK( pContext );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Publish( MQTTContext_t * pContext,
- const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId )
-{
- size_t headerSize = 0UL;
- size_t remainingLength = 0UL;
- size_t packetSize = 0UL;
- MQTTPublishState_t publishStatus = MQTTStateNull;
- bool stateUpdateHookExecuted = false;
-
- /* 1 header byte + 4 bytes (maximum) required for encoding the length +
- * 2 bytes for topic string. */
- uint8_t mqttHeader[ 7 ];
-
- /* Validate arguments. */
- MQTTStatus_t status = validatePublishParams( pContext, pPublishInfo, packetId );
-
- if( status == MQTTSuccess )
- {
- /* Get the remaining length and packet size.*/
- status = MQTT_GetPublishPacketSize( pPublishInfo,
- &remainingLength,
- &packetSize );
- }
-
- if( status == MQTTSuccess )
- {
- status = MQTT_SerializePublishHeaderWithoutTopic( pPublishInfo,
- remainingLength,
- mqttHeader,
- &headerSize );
- }
-
- if( ( status == MQTTSuccess ) && ( pPublishInfo->qos > MQTTQoS0 ) )
- {
- MQTT_PRE_STATE_UPDATE_HOOK( pContext );
-
- /* Set the flag so that the corresponding hook can be called later. */
- stateUpdateHookExecuted = true;
-
- status = MQTT_ReserveState( pContext,
- packetId,
- pPublishInfo->qos );
-
- /* State already exists for a duplicate packet.
- * If a state doesn't exist, it will be handled as a new publish in
- * state engine. */
- if( ( status == MQTTStateCollision ) && ( pPublishInfo->dup == true ) )
- {
- status = MQTTSuccess;
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Take the mutex as multiple send calls are required for sending this
- * packet. */
- MQTT_PRE_SEND_HOOK( pContext );
-
- status = sendPublishWithoutCopy( pContext,
- pPublishInfo,
- mqttHeader,
- headerSize,
- packetId );
-
- /* Give the mutex away for the next taker. */
- MQTT_POST_SEND_HOOK( pContext );
- }
-
- if( ( status == MQTTSuccess ) &&
- ( pPublishInfo->qos > MQTTQoS0 ) )
- {
- /* Update state machine after PUBLISH is sent.
- * Only to be done for QoS1 or QoS2. */
- status = MQTT_UpdateStatePublish( pContext,
- packetId,
- MQTT_SEND,
- pPublishInfo->qos,
- &publishStatus );
-
- if( status != MQTTSuccess )
- {
- LogError( ( "Update state for publish failed with status %s."
- " However PUBLISH packet was sent to the broker."
- " Any further handling of ACKs for the packet Id"
- " will fail.",
- MQTT_Status_strerror( status ) ) );
- }
- }
-
- if( stateUpdateHookExecuted == true )
- {
- /* Regardless of the status, if the mutex was taken due to the
- * packet being of QoS > QoS0, then it should be relinquished. */
- MQTT_POST_STATE_UPDATE_HOOK( pContext );
- }
-
- if( status != MQTTSuccess )
- {
- LogError( ( "MQTT PUBLISH failed with status %s.",
- MQTT_Status_strerror( status ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Ping( MQTTContext_t * pContext )
-{
- int32_t sendResult = 0;
- MQTTStatus_t status = MQTTSuccess;
- size_t packetSize = 0U;
- /* MQTT ping packets are of fixed length. */
- uint8_t pingreqPacket[ 2U ];
- MQTTFixedBuffer_t localBuffer;
-
- localBuffer.pBuffer = pingreqPacket;
- localBuffer.size = 2U;
-
- if( pContext == NULL )
- {
- LogError( ( "pContext is NULL." ) );
- status = MQTTBadParameter;
- }
-
- if( status == MQTTSuccess )
- {
- /* Get MQTT PINGREQ packet size. */
- status = MQTT_GetPingreqPacketSize( &packetSize );
-
- if( status == MQTTSuccess )
- {
- LogDebug( ( "MQTT PINGREQ packet size is %lu.",
- ( unsigned long ) packetSize ) );
- }
- else
- {
- LogError( ( "Failed to get the PINGREQ packet size." ) );
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Serialize MQTT PINGREQ. */
- status = MQTT_SerializePingreq( &localBuffer );
- }
-
- if( status == MQTTSuccess )
- {
- /* Take the mutex as the send call should not be interrupted in
- * between. */
- MQTT_PRE_SEND_HOOK( pContext );
-
- /* Send the serialized PINGREQ packet to transport layer.
- * Here, we do not use the vectored IO approach for efficiency as the
- * Ping packet does not have numerous fields which need to be copied
- * from the user provided buffers. Thus it can be sent directly. */
- sendResult = sendBuffer( pContext,
- localBuffer.pBuffer,
- 2U );
-
- /* Give the mutex away. */
- MQTT_POST_SEND_HOOK( pContext );
-
- /* It is an error to not send the entire PINGREQ packet. */
- if( sendResult < ( int32_t ) packetSize )
- {
- LogError( ( "Transport send failed for PINGREQ packet." ) );
- status = MQTTSendFailed;
- }
- else
- {
- pContext->pingReqSendTimeMs = pContext->lastPacketTxTime;
- pContext->waitingForPingResp = true;
- LogDebug( ( "Sent %ld bytes of PINGREQ packet.",
- ( long int ) sendResult ) );
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Unsubscribe( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId )
-{
- size_t remainingLength = 0UL, packetSize = 0UL;
-
- /* Validate arguments. */
- MQTTStatus_t status = validateSubscribeUnsubscribeParams( pContext,
- pSubscriptionList,
- subscriptionCount,
- packetId );
-
- if( status == MQTTSuccess )
- {
- /* Get the remaining length and packet size.*/
- status = MQTT_GetUnsubscribePacketSize( pSubscriptionList,
- subscriptionCount,
- &remainingLength,
- &packetSize );
- LogDebug( ( "UNSUBSCRIBE packet size is %lu and remaining length is %lu.",
- ( unsigned long ) packetSize,
- ( unsigned long ) remainingLength ) );
- }
-
- if( status == MQTTSuccess )
- {
- /* Take the mutex because the below call should not be interrupted. */
- MQTT_PRE_SEND_HOOK( pContext );
-
- status = sendUnsubscribeWithoutCopy( pContext,
- pSubscriptionList,
- subscriptionCount,
- packetId,
- remainingLength );
-
- /* Give the mutex away. */
- MQTT_POST_SEND_HOOK( pContext );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_Disconnect( MQTTContext_t * pContext )
-{
- size_t packetSize = 0U;
- int32_t sendResult = 0;
- MQTTStatus_t status = MQTTSuccess;
- MQTTFixedBuffer_t localBuffer;
- uint8_t disconnectPacket[ 2U ];
-
- localBuffer.pBuffer = disconnectPacket;
- localBuffer.size = 2U;
-
- /* Validate arguments. */
- if( pContext == NULL )
- {
- LogError( ( "pContext cannot be NULL." ) );
- status = MQTTBadParameter;
- }
-
- if( status == MQTTSuccess )
- {
- /* Get MQTT DISCONNECT packet size. */
- status = MQTT_GetDisconnectPacketSize( &packetSize );
- LogDebug( ( "MQTT DISCONNECT packet size is %lu.",
- ( unsigned long ) packetSize ) );
- }
-
- if( status == MQTTSuccess )
- {
- /* Serialize MQTT DISCONNECT packet. */
- status = MQTT_SerializeDisconnect( &localBuffer );
- }
-
- if( status == MQTTSuccess )
- {
- /* Take the mutex because the below call should not be interrupted. */
- MQTT_PRE_SEND_HOOK( pContext );
-
- /* Here we do not use vectors as the disconnect packet has fixed fields
- * which do not reside in user provided buffers. Thus, it can be sent
- * using a simple send call. */
- sendResult = sendBuffer( pContext,
- localBuffer.pBuffer,
- packetSize );
-
- /* Give the mutex away. */
- MQTT_POST_SEND_HOOK( pContext );
-
- if( sendResult < ( int32_t ) packetSize )
- {
- LogError( ( "Transport send failed for DISCONNECT packet." ) );
- status = MQTTSendFailed;
- }
- else
- {
- LogDebug( ( "Sent %ld bytes of DISCONNECT packet.",
- ( long int ) sendResult ) );
- }
- }
-
- if( status == MQTTSuccess )
- {
- LogInfo( ( "Disconnected from the broker." ) );
- pContext->connectStatus = MQTTNotConnected;
-
- /* Reset the index and clean the buffer on a successful disconnect. */
- pContext->index = 0;
- ( void ) memset( pContext->networkBuffer.pBuffer, 0, pContext->networkBuffer.size );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_ProcessLoop( MQTTContext_t * pContext )
-{
- MQTTStatus_t status = MQTTBadParameter;
-
- if( pContext == NULL )
- {
- LogError( ( "Invalid input parameter: MQTT Context cannot be NULL." ) );
- }
- else if( pContext->getTime == NULL )
- {
- LogError( ( "Invalid input parameter: MQTT Context must have valid getTime." ) );
- }
- else if( pContext->networkBuffer.pBuffer == NULL )
- {
- LogError( ( "Invalid input parameter: The MQTT context's networkBuffer must not be NULL." ) );
- }
- else
- {
- pContext->controlPacketSent = false;
- status = receiveSingleIteration( pContext, true );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_ReceiveLoop( MQTTContext_t * pContext )
-{
- MQTTStatus_t status = MQTTBadParameter;
-
- if( pContext == NULL )
- {
- LogError( ( "Invalid input parameter: MQTT Context cannot be NULL." ) );
- }
- else if( pContext->getTime == NULL )
- {
- LogError( ( "Invalid input parameter: MQTT Context must have a valid getTime function." ) );
- }
- else if( pContext->networkBuffer.pBuffer == NULL )
- {
- LogError( ( "Invalid input parameter: MQTT context's networkBuffer must not be NULL." ) );
- }
- else
- {
- status = receiveSingleIteration( pContext, false );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-uint16_t MQTT_GetPacketId( MQTTContext_t * pContext )
-{
- uint16_t packetId = 0U;
-
- if( pContext != NULL )
- {
- MQTT_PRE_STATE_UPDATE_HOOK( pContext );
-
- packetId = pContext->nextPacketId;
-
- /* A packet ID of zero is not a valid packet ID. When the max ID
- * is reached the next one should start at 1. */
- if( pContext->nextPacketId == ( uint16_t ) UINT16_MAX )
- {
- pContext->nextPacketId = 1;
- }
- else
- {
- pContext->nextPacketId++;
- }
-
- MQTT_POST_STATE_UPDATE_HOOK( pContext );
- }
-
- return packetId;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_MatchTopic( const char * pTopicName,
- const uint16_t topicNameLength,
- const char * pTopicFilter,
- const uint16_t topicFilterLength,
- bool * pIsMatch )
-{
- MQTTStatus_t status = MQTTSuccess;
- bool topicFilterStartsWithWildcard = false;
- bool matchStatus = false;
-
- if( ( pTopicName == NULL ) || ( topicNameLength == 0u ) )
- {
- LogError( ( "Invalid paramater: Topic name should be non-NULL and its "
- "length should be > 0: TopicName=%p, TopicNameLength=%hu",
- ( void * ) pTopicName,
- ( unsigned short ) topicNameLength ) );
-
- status = MQTTBadParameter;
- }
- else if( ( pTopicFilter == NULL ) || ( topicFilterLength == 0u ) )
- {
- LogError( ( "Invalid paramater: Topic filter should be non-NULL and "
- "its length should be > 0: TopicName=%p, TopicFilterLength=%hu",
- ( void * ) pTopicFilter,
- ( unsigned short ) topicFilterLength ) );
- status = MQTTBadParameter;
- }
- else if( pIsMatch == NULL )
- {
- LogError( ( "Invalid paramater: Output parameter, pIsMatch, is NULL" ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Check for an exact match if the incoming topic name and the registered
- * topic filter length match. */
- if( topicNameLength == topicFilterLength )
- {
- matchStatus = strncmp( pTopicName, pTopicFilter, topicNameLength ) == 0;
- }
-
- if( matchStatus == false )
- {
- /* If an exact match was not found, match against wildcard characters in
- * topic filter.*/
-
- /* Determine if topic filter starts with a wildcard. */
- topicFilterStartsWithWildcard = ( pTopicFilter[ 0 ] == '+' ) ||
- ( pTopicFilter[ 0 ] == '#' );
-
- /* Note: According to the MQTT 3.1.1 specification, incoming PUBLISH topic names
- * starting with "$" character cannot be matched against topic filter starting with
- * a wildcard, i.e. for example, "$SYS/sport" cannot be matched with "#" or
- * "+/sport" topic filters. */
- if( !( ( pTopicName[ 0 ] == '$' ) && ( topicFilterStartsWithWildcard == true ) ) )
- {
- matchStatus = matchTopicFilter( pTopicName, topicNameLength, pTopicFilter, topicFilterLength );
- }
- }
-
- /* Update the output parameter with the match result. */
- *pIsMatch = matchStatus;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetSubAckStatusCodes( const MQTTPacketInfo_t * pSubackPacket,
- uint8_t ** pPayloadStart,
- size_t * pPayloadSize )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pSubackPacket == NULL )
- {
- LogError( ( "Invalid parameter: pSubackPacket is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pPayloadStart == NULL )
- {
- LogError( ( "Invalid parameter: pPayloadStart is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pPayloadSize == NULL )
- {
- LogError( ( "Invalid parameter: pPayloadSize is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pSubackPacket->type != MQTT_PACKET_TYPE_SUBACK )
- {
- LogError( ( "Invalid parameter: Input packet is not a SUBACK packet: "
- "ExpectedType=%02x, InputType=%02x",
- ( int ) MQTT_PACKET_TYPE_SUBACK,
- ( int ) pSubackPacket->type ) );
- status = MQTTBadParameter;
- }
- else if( pSubackPacket->pRemainingData == NULL )
- {
- LogError( ( "Invalid parameter: pSubackPacket->pRemainingData is NULL" ) );
- status = MQTTBadParameter;
- }
-
- /* A SUBACK must have a remaining length of at least 3 to accommodate the
- * packet identifier and at least 1 return code. */
- else if( pSubackPacket->remainingLength < 3U )
- {
- LogError( ( "Invalid parameter: Packet remaining length is invalid: "
- "Should be greater than 2 for SUBACK packet: InputRemainingLength=%lu",
- ( unsigned long ) pSubackPacket->remainingLength ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* According to the MQTT 3.1.1 protocol specification, the "Remaining Length" field is a
- * length of the variable header (2 bytes) plus the length of the payload.
- * Therefore, we add 2 positions for the starting address of the payload, and
- * subtract 2 bytes from the remaining length for the length of the payload.*/
- *pPayloadStart = &pSubackPacket->pRemainingData[ sizeof( uint16_t ) ];
- *pPayloadSize = pSubackPacket->remainingLength - sizeof( uint16_t );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-const char * MQTT_Status_strerror( MQTTStatus_t status )
-{
- const char * str = NULL;
-
- switch( status )
- {
- case MQTTSuccess:
- str = "MQTTSuccess";
- break;
-
- case MQTTBadParameter:
- str = "MQTTBadParameter";
- break;
-
- case MQTTNoMemory:
- str = "MQTTNoMemory";
- break;
-
- case MQTTSendFailed:
- str = "MQTTSendFailed";
- break;
-
- case MQTTRecvFailed:
- str = "MQTTRecvFailed";
- break;
-
- case MQTTBadResponse:
- str = "MQTTBadResponse";
- break;
-
- case MQTTServerRefused:
- str = "MQTTServerRefused";
- break;
-
- case MQTTNoDataAvailable:
- str = "MQTTNoDataAvailable";
- break;
-
- case MQTTIllegalState:
- str = "MQTTIllegalState";
- break;
-
- case MQTTStateCollision:
- str = "MQTTStateCollision";
- break;
-
- case MQTTKeepAliveTimeout:
- str = "MQTTKeepAliveTimeout";
- break;
-
- default:
- str = "Invalid MQTT Status code";
- break;
- }
-
- return str;
-}
-
-/*-----------------------------------------------------------*/
diff --git a/project/coreMQTT/coreMQTT/core_mqtt.h b/project/coreMQTT/coreMQTT/core_mqtt.h
deleted file mode 100644
index a9f14c5..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt.h
+++ /dev/null
@@ -1,1015 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt.h
- * @brief User-facing functions of the MQTT 3.1.1 library.
- */
-#ifndef CORE_MQTT_H
-#define CORE_MQTT_H
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/* Include MQTT serializer library. */
-#include "core_mqtt_serializer.h"
-
-/* Include transport interface. */
-#include "transport_interface.h"
-
-/**
- * @cond DOXYGEN_IGNORE
- * The current version of this library.
- */
-#define MQTT_LIBRARY_VERSION "v2.1.1"
-/** @endcond */
-
-/**
- * @ingroup mqtt_constants
- * @brief Invalid packet identifier.
- *
- * Zero is an invalid packet identifier as per MQTT v3.1.1 spec.
- */
-#define MQTT_PACKET_ID_INVALID ( ( uint16_t ) 0U )
-
-/* Structures defined in this file. */
-struct MQTTPubAckInfo;
-struct MQTTContext;
-struct MQTTDeserializedInfo;
-
-/**
- * @ingroup mqtt_callback_types
- * @brief Application provided function to query the time elapsed since a given
- * epoch in milliseconds.
- *
- * @note The timer should be a monotonic timer. It just needs to provide an
- * incrementing count of milliseconds elapsed since a given epoch.
- *
- * @return The time elapsed in milliseconds.
- */
-typedef uint32_t (* MQTTGetCurrentTimeFunc_t )( void );
-
-/**
- * @ingroup mqtt_callback_types
- * @brief Application callback for receiving incoming publishes and incoming
- * acks.
- *
- * @note This callback will be called only if packets are deserialized with a
- * result of #MQTTSuccess or #MQTTServerRefused. The latter can be obtained
- * when deserializing a SUBACK, indicating a broker's rejection of a subscribe.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pPacketInfo Information on the type of incoming MQTT packet.
- * @param[in] pDeserializedInfo Deserialized information from incoming packet.
- */
-typedef void (* MQTTEventCallback_t )( struct MQTTContext * pContext,
- struct MQTTPacketInfo * pPacketInfo,
- struct MQTTDeserializedInfo * pDeserializedInfo );
-
-/**
- * @ingroup mqtt_enum_types
- * @brief Values indicating if an MQTT connection exists.
- */
-typedef enum MQTTConnectionStatus
-{
- MQTTNotConnected, /**< @brief MQTT Connection is inactive. */
- MQTTConnected /**< @brief MQTT Connection is active. */
-} MQTTConnectionStatus_t;
-
-/**
- * @ingroup mqtt_enum_types
- * @brief The state of QoS 1 or QoS 2 MQTT publishes, used in the state engine.
- */
-typedef enum MQTTPublishState
-{
- MQTTStateNull = 0, /**< @brief An empty state with no corresponding PUBLISH. */
- MQTTPublishSend, /**< @brief The library will send an outgoing PUBLISH packet. */
- MQTTPubAckSend, /**< @brief The library will send a PUBACK for a received PUBLISH. */
- MQTTPubRecSend, /**< @brief The library will send a PUBREC for a received PUBLISH. */
- MQTTPubRelSend, /**< @brief The library will send a PUBREL for a received PUBREC. */
- MQTTPubCompSend, /**< @brief The library will send a PUBCOMP for a received PUBREL. */
- MQTTPubAckPending, /**< @brief The library is awaiting a PUBACK for an outgoing PUBLISH. */
- MQTTPubRecPending, /**< @brief The library is awaiting a PUBREC for an outgoing PUBLISH. */
- MQTTPubRelPending, /**< @brief The library is awaiting a PUBREL for an incoming PUBLISH. */
- MQTTPubCompPending, /**< @brief The library is awaiting a PUBCOMP for an outgoing PUBLISH. */
- MQTTPublishDone /**< @brief The PUBLISH has been completed. */
-} MQTTPublishState_t;
-
-/**
- * @ingroup mqtt_enum_types
- * @brief Packet types used in acknowledging QoS 1 or QoS 2 publishes.
- */
-typedef enum MQTTPubAckType
-{
- MQTTPuback, /**< @brief PUBACKs are sent in response to a QoS 1 PUBLISH. */
- MQTTPubrec, /**< @brief PUBRECs are sent in response to a QoS 2 PUBLISH. */
- MQTTPubrel, /**< @brief PUBRELs are sent in response to a PUBREC. */
- MQTTPubcomp /**< @brief PUBCOMPs are sent in response to a PUBREL. */
-} MQTTPubAckType_t;
-
-/**
- * @ingroup mqtt_enum_types
- * @brief The status codes in the SUBACK response to a subscription request.
- */
-typedef enum MQTTSubAckStatus
-{
- MQTTSubAckSuccessQos0 = 0x00, /**< @brief Success with a maximum delivery at QoS 0. */
- MQTTSubAckSuccessQos1 = 0x01, /**< @brief Success with a maximum delivery at QoS 1. */
- MQTTSubAckSuccessQos2 = 0x02, /**< @brief Success with a maximum delivery at QoS 2. */
- MQTTSubAckFailure = 0x80 /**< @brief Failure. */
-} MQTTSubAckStatus_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief An element of the state engine records for QoS 1 or Qos 2 publishes.
- */
-typedef struct MQTTPubAckInfo
-{
- uint16_t packetId; /**< @brief The packet ID of the original PUBLISH. */
- MQTTQoS_t qos; /**< @brief The QoS of the original PUBLISH. */
- MQTTPublishState_t publishState; /**< @brief The current state of the publish process. */
-} MQTTPubAckInfo_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief A struct representing an MQTT connection.
- */
-typedef struct MQTTContext
-{
- /**
- * @brief State engine records for outgoing publishes.
- */
- MQTTPubAckInfo_t * outgoingPublishRecords;
-
- /**
- * @brief State engine records for incoming publishes.
- */
- MQTTPubAckInfo_t * incomingPublishRecords;
-
- /**
- * @brief The maximum number of outgoing publish records.
- */
- size_t outgoingPublishRecordMaxCount;
-
- /**
- * @brief The maximum number of incoming publish records.
- */
- size_t incomingPublishRecordMaxCount;
-
- /**
- * @brief The transport interface used by the MQTT connection.
- */
- TransportInterface_t transportInterface;
-
- /**
- * @brief The buffer used in sending and receiving packets from the network.
- */
- MQTTFixedBuffer_t networkBuffer;
-
- /**
- * @brief The next available ID for outgoing MQTT packets.
- */
- uint16_t nextPacketId;
-
- /**
- * @brief Whether the context currently has a connection to the broker.
- */
- MQTTConnectionStatus_t connectStatus;
-
- /**
- * @brief Function used to get millisecond timestamps.
- */
- MQTTGetCurrentTimeFunc_t getTime;
-
- /**
- * @brief Callback function used to give deserialized MQTT packets to the application.
- */
- MQTTEventCallback_t appCallback;
-
- /**
- * @brief Timestamp of the last packet sent by the library.
- */
- uint32_t lastPacketTxTime;
-
- /**
- * @brief Timestamp of the last packet received by the library.
- */
- uint32_t lastPacketRxTime;
-
- /**
- * @brief Whether the library sent a packet during a call of #MQTT_ProcessLoop or
- * #MQTT_ReceiveLoop.
- */
- bool controlPacketSent;
-
- /**
- * @brief Index to keep track of the number of bytes received in network buffer.
- */
- size_t index;
-
- /* Keep alive members. */
- uint16_t keepAliveIntervalSec; /**< @brief Keep Alive interval. */
- uint32_t pingReqSendTimeMs; /**< @brief Timestamp of the last sent PINGREQ. */
- bool waitingForPingResp; /**< @brief If the library is currently awaiting a PINGRESP. */
-} MQTTContext_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief Struct to hold deserialized packet information for an #MQTTEventCallback_t
- * callback.
- */
-typedef struct MQTTDeserializedInfo
-{
- uint16_t packetIdentifier; /**< @brief Packet ID of deserialized packet. */
- MQTTPublishInfo_t * pPublishInfo; /**< @brief Pointer to deserialized publish info. */
- MQTTStatus_t deserializationResult; /**< @brief Return code of deserialization. */
-} MQTTDeserializedInfo_t;
-
-/**
- * @brief Initialize an MQTT context.
- *
- * This function must be called on an #MQTTContext_t before any other function.
- *
- * @note The #MQTTGetCurrentTimeFunc_t function for querying time must be defined. If
- * there is no time implementation, it is the responsibility of the application
- * to provide a dummy function to always return 0, provide 0 timeouts for
- * all calls to #MQTT_Connect, #MQTT_ProcessLoop, and #MQTT_ReceiveLoop and configure
- * the #MQTT_RECV_POLLING_TIMEOUT_MS and #MQTT_SEND_TIMEOUT_MS configurations
- * to be 0. This will result in loop functions running for a single iteration, and
- * #MQTT_Connect relying on #MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT to receive the CONNACK packet.
- *
- * @param[in] pContext The context to initialize.
- * @param[in] pTransportInterface The transport interface to use with the context.
- * @param[in] getTimeFunction The time utility function which can return the amount of time
- * (in milliseconds) elapsed since a given epoch. This function will be used to ensure that
- * timeouts in the API calls are met and keep-alive messages are sent on time.
- * @param[in] userCallback The user callback to use with the context to notify about incoming
- * packet events.
- * @param[in] pNetworkBuffer Network buffer provided for the context. This buffer will be used
- * to receive incoming messages from the broker. This buffer must remain valid and in scope
- * for the entire lifetime of the @p pContext and must not be used by another context and/or
- * application.
- *
- * @return #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Function for obtaining a timestamp.
- * uint32_t getTimeStampMs();
- * // Callback function for receiving packets.
- * void eventCallback(
- * MQTTContext_t * pContext,
- * MQTTPacketInfo_t * pPacketInfo,
- * MQTTDeserializedInfo_t * pDeserializedInfo
- * );
- * // Network send.
- * int32_t networkSend( NetworkContext_t * pContext, const void * pBuffer, size_t bytes );
- * // Network receive.
- * int32_t networkRecv( NetworkContext_t * pContext, void * pBuffer, size_t bytes );
- *
- * MQTTContext_t mqttContext;
- * TransportInterface_t transport;
- * MQTTFixedBuffer_t fixedBuffer;
- * // Create a globally accessible buffer which remains in scope for the entire duration
- * // of the MQTT context.
- * uint8_t buffer[ 1024 ];
- *
- * // Clear context.
- * memset( ( void * ) &mqttContext, 0x00, sizeof( MQTTContext_t ) );
- *
- * // Set transport interface members.
- * transport.pNetworkContext = &someTransportContext;
- * transport.send = networkSend;
- * transport.recv = networkRecv;
- *
- * // Set buffer members.
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = 1024;
- *
- * status = MQTT_Init( &mqttContext, &transport, getTimeStampMs, eventCallback, &fixedBuffer );
- *
- * if( status == MQTTSuccess )
- * {
- * // Do something with mqttContext. The transport and fixedBuffer structs were
- * // copied into the context, so the original structs do not need to stay in scope.
- * // However, the memory pointed to by the fixedBuffer.pBuffer must remain in scope.
- * }
- * @endcode
- */
-/* @[declare_mqtt_init] */
-MQTTStatus_t MQTT_Init( MQTTContext_t * pContext,
- const TransportInterface_t * pTransportInterface,
- MQTTGetCurrentTimeFunc_t getTimeFunction,
- MQTTEventCallback_t userCallback,
- const MQTTFixedBuffer_t * pNetworkBuffer );
-/* @[declare_mqtt_init] */
-
-/**
- * @brief Initialize an MQTT context for QoS > 0.
- *
- * This function must be called on an #MQTTContext_t after MQTT_Init and before any other function.
- *
- * @param[in] pContext The context to initialize.
- * @param[in] pOutgoingPublishRecords Pointer to memory which will be used to store state of outgoing
- * publishes.
- * @param[in] outgoingPublishCount Maximum number of records which can be kept in the memory
- * pointed to by @p pOutgoingPublishRecords.
- * @param[in] pIncomingPublishRecords Pointer to memory which will be used to store state of incoming
- * publishes.
- * @param[in] incomingPublishCount Maximum number of records which can be kept in the memory
- * pointed to by @p pIncomingPublishRecords.
- *
- * @return #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Function for obtaining a timestamp.
- * uint32_t getTimeStampMs();
- * // Callback function for receiving packets.
- * void eventCallback(
- * MQTTContext_t * pContext,
- * MQTTPacketInfo_t * pPacketInfo,
- * MQTTDeserializedInfo_t * pDeserializedInfo
- * );
- * // Network send.
- * int32_t networkSend( NetworkContext_t * pContext, const void * pBuffer, size_t bytes );
- * // Network receive.
- * int32_t networkRecv( NetworkContext_t * pContext, void * pBuffer, size_t bytes );
- *
- * MQTTContext_t mqttContext;
- * TransportInterface_t transport;
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ 1024 ];
- * const size_t outgoingPublishCount = 30;
- * MQTTPubAckInfo_t outgoingPublishes[ outgoingPublishCount ];
- *
- * // Clear context.
- * memset( ( void * ) &mqttContext, 0x00, sizeof( MQTTContext_t ) );
- *
- * // Set transport interface members.
- * transport.pNetworkContext = &someTransportContext;
- * transport.send = networkSend;
- * transport.recv = networkRecv;
- *
- * // Set buffer members.
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = 1024;
- *
- * status = MQTT_Init( &mqttContext, &transport, getTimeStampMs, eventCallback, &fixedBuffer );
- *
- * if( status == MQTTSuccess )
- * {
- * // We do not expect any incoming publishes in this example, therefore the incoming
- * // publish pointer is NULL and the count is zero.
- * status = MQTT_InitStatefulQoS( &mqttContext, outgoingPublishes, outgoingPublishCount, NULL, 0 );
- *
- * // Now QoS1 and/or QoS2 publishes can be sent with this context.
- * }
- * @endcode
- */
-/* @[declare_mqtt_initstatefulqos] */
-MQTTStatus_t MQTT_InitStatefulQoS( MQTTContext_t * pContext,
- MQTTPubAckInfo_t * pOutgoingPublishRecords,
- size_t outgoingPublishCount,
- MQTTPubAckInfo_t * pIncomingPublishRecords,
- size_t incomingPublishCount );
-/* @[declare_mqtt_initstatefulqos] */
-
-/**
- * @brief Establish an MQTT session.
- *
- * This function will send MQTT CONNECT packet and receive a CONNACK packet. The
- * send and receive from the network is done through the transport interface.
- *
- * The maximum time this function waits for a CONNACK is decided in one of the
- * following ways:
- * 1. If @p timeoutMs is greater than 0:
- * #MQTTContext_t.getTime is used to ensure that the function does not wait
- * more than @p timeoutMs for CONNACK.
- * 2. If @p timeoutMs is 0:
- * The network receive for CONNACK is retried up to the number of times
- * configured by #MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT.
- *
- * @note If a dummy #MQTTGetCurrentTimeFunc_t was passed to #MQTT_Init, then a
- * timeout value of 0 MUST be passed to the API, and the #MQTT_RECV_POLLING_TIMEOUT_MS
- * and #MQTT_SEND_TIMEOUT_MS timeout configurations MUST be set to 0.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pConnectInfo MQTT CONNECT packet information.
- * @param[in] pWillInfo Last Will and Testament. Pass NULL if Last Will and
- * Testament is not used.
- * @param[in] timeoutMs Maximum time in milliseconds to wait for a CONNACK packet.
- * A zero timeout makes use of the retries for receiving CONNACK as configured with
- * #MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT.
- * @param[out] pSessionPresent This value will be set to true if a previous session
- * was present; otherwise it will be set to false. It is only relevant if not
- * establishing a clean session.
- *
- * @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to
- * hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSendFailed if transport send failed;
- * #MQTTRecvFailed if transport receive failed for CONNACK;
- * #MQTTNoDataAvailable if no data available to receive in transport until
- * the @p timeoutMs for CONNACK;
- * #MQTTSuccess otherwise.
- *
- * @note This API may spend more time than provided in the timeoutMS parameters in
- * certain conditions as listed below:
- *
- * 1. Timeouts are incorrectly configured - If the timeoutMS is less than the
- * transport receive timeout and if a CONNACK packet is not received within
- * the transport receive timeout, the API will spend the transport receive
- * timeout (which is more time than the timeoutMs). It is the case of incorrect
- * timeout configuration as the timeoutMs parameter passed to this API must be
- * greater than the transport receive timeout. Please refer to the transport
- * interface documentation for more details about timeout configurations.
- *
- * 2. Partial CONNACK packet is received right before the expiry of the timeout - It
- * is possible that first two bytes of CONNACK packet (packet type and remaining
- * length) are received right before the expiry of the timeoutMS. In that case,
- * the API makes one more network receive call in an attempt to receive the remaining
- * 2 bytes. In the worst case, it can happen that the remaining 2 bytes are never
- * received and this API will end up spending timeoutMs + transport receive timeout.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTConnectInfo_t connectInfo = { 0 };
- * MQTTPublishInfo_t willInfo = { 0 };
- * bool sessionPresent;
- * // This is assumed to have been initialized before calling this function.
- * MQTTContext_t * pContext;
- *
- * // True for creating a new session with broker, false if we want to resume an old one.
- * connectInfo.cleanSession = true;
- * // Client ID must be unique to broker. This field is required.
- * connectInfo.pClientIdentifier = "someClientID";
- * connectInfo.clientIdentifierLength = strlen( connectInfo.pClientIdentifier );
- *
- * // The following fields are optional.
- * // Value for keep alive.
- * connectInfo.keepAliveSeconds = 60;
- * // Optional username and password.
- * connectInfo.pUserName = "someUserName";
- * connectInfo.userNameLength = strlen( connectInfo.pUserName );
- * connectInfo.pPassword = "somePassword";
- * connectInfo.passwordLength = strlen( connectInfo.pPassword );
- *
- * // The last will and testament is optional, it will be published by the broker
- * // should this client disconnect without sending a DISCONNECT packet.
- * willInfo.qos = MQTTQoS0;
- * willInfo.pTopicName = "/lwt/topic/name";
- * willInfo.topicNameLength = strlen( willInfo.pTopicName );
- * willInfo.pPayload = "LWT Message";
- * willInfo.payloadLength = strlen( "LWT Message" );
- *
- * // Send the connect packet. Use 100 ms as the timeout to wait for the CONNACK packet.
- * status = MQTT_Connect( pContext, &connectInfo, &willInfo, 100, &sessionPresent );
- *
- * if( status == MQTTSuccess )
- * {
- * // Since we requested a clean session, this must be false
- * assert( sessionPresent == false );
- *
- * // Do something with the connection.
- * }
- * @endcode
- */
-/* @[declare_mqtt_connect] */
-MQTTStatus_t MQTT_Connect( MQTTContext_t * pContext,
- const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- uint32_t timeoutMs,
- bool * pSessionPresent );
-/* @[declare_mqtt_connect] */
-
-/**
- * @brief Sends MQTT SUBSCRIBE for the given list of topic filters to
- * the broker.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pSubscriptionList Array of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in @ pSubscriptionList
- * array.
- * @param[in] packetId Packet ID generated by #MQTT_GetPacketId.
- *
- * @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to
- * hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSendFailed if transport write failed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTSubscribeInfo_t subscriptionList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 };
- * uint16_t packetId;
- * // This context is assumed to be initialized and connected.
- * MQTTContext_t * pContext;
- * // This is assumed to be a list of filters we want to subscribe to.
- * const char * filters[ NUMBER_OF_SUBSCRIPTIONS ];
- *
- * // Set each subscription.
- * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )
- * {
- * subscriptionList[ i ].qos = MQTTQoS0;
- * // Each subscription needs a topic filter.
- * subscriptionList[ i ].pTopicFilter = filters[ i ];
- * subscriptionList[ i ].topicFilterLength = strlen( filters[ i ] );
- * }
- *
- * // Obtain a new packet id for the subscription.
- * packetId = MQTT_GetPacketId( pContext );
- *
- * status = MQTT_Subscribe( pContext, &subscriptionList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, packetId );
- *
- * if( status == MQTTSuccess )
- * {
- * // We must now call MQTT_ReceiveLoop() or MQTT_ProcessLoop() to receive the SUBACK.
- * // If the broker accepts the subscription we can now receive publishes
- * // on the requested topics.
- * }
- * @endcode
- */
-/* @[declare_mqtt_subscribe] */
-MQTTStatus_t MQTT_Subscribe( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId );
-/* @[declare_mqtt_subscribe] */
-
-/**
- * @brief Publishes a message to the given topic name.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @param[in] packetId packet ID generated by #MQTT_GetPacketId.
- *
- * @return #MQTTNoMemory if pBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSendFailed if transport write failed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTPublishInfo_t publishInfo;
- * uint16_t packetId;
- * // This context is assumed to be initialized and connected.
- * MQTTContext_t * pContext;
- *
- * // QoS of publish.
- * publishInfo.qos = MQTTQoS1;
- * publishInfo.pTopicName = "/some/topic/name";
- * publishInfo.topicNameLength = strlen( publishInfo.pTopicName );
- * publishInfo.pPayload = "Hello World!";
- * publishInfo.payloadLength = strlen( "Hello World!" );
- *
- * // Packet ID is needed for QoS > 0.
- * packetId = MQTT_GetPacketId( pContext );
- *
- * status = MQTT_Publish( pContext, &publishInfo, packetId );
- *
- * if( status == MQTTSuccess )
- * {
- * // Since the QoS is > 0, we will need to call MQTT_ReceiveLoop()
- * // or MQTT_ProcessLoop() to process the publish acknowledgments.
- * }
- * @endcode
- */
-/* @[declare_mqtt_publish] */
-MQTTStatus_t MQTT_Publish( MQTTContext_t * pContext,
- const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId );
-/* @[declare_mqtt_publish] */
-
-/**
- * @brief Cancels an outgoing publish callback (only for QoS > QoS0) by
- * removing it from the pending ACK list.
- *
- * @note This cannot cancel the actual publish as that might have already
- * been sent to the broker. This only removes the details of the given packet
- * ID from the list of unACKed packet. That allows the caller to free any memory
- * associated with the publish payload, topic string etc. Also, after this API
- * call, the user provided callback will not be invoked when the ACK packet is
- * received.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] packetId packet ID corresponding to the outstanding publish.
- *
- * @return #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- */
-/* @[declare_mqtt_cancelcallback] */
-MQTTStatus_t MQTT_CancelCallback( const MQTTContext_t * pContext,
- uint16_t packetId );
-/* @[declare_mqtt_cancelcallback] */
-
-/**
- * @brief Sends an MQTT PINGREQ to broker.
- *
- * @param[in] pContext Initialized and connected MQTT context.
- *
- * @return #MQTTNoMemory if pBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSendFailed if transport write failed;
- * #MQTTSuccess otherwise.
- */
-/* @[declare_mqtt_ping] */
-MQTTStatus_t MQTT_Ping( MQTTContext_t * pContext );
-/* @[declare_mqtt_ping] */
-
-/**
- * @brief Sends MQTT UNSUBSCRIBE for the given list of topic filters to
- * the broker.
- *
- * @param[in] pContext Initialized MQTT context.
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[in] packetId packet ID generated by #MQTT_GetPacketId.
- *
- * @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to
- * hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSendFailed if transport write failed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTSubscribeInfo_t unsubscribeList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 };
- * uint16_t packetId;
- * // This context is assumed to be initialized and connected.
- * MQTTContext_t * pContext;
- * // This is assumed to be a list of filters we want to unsubscribe from.
- * const char * filters[ NUMBER_OF_SUBSCRIPTIONS ];
- *
- * // Set information for each unsubscribe request.
- * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )
- * {
- * unsubscribeList[ i ].pTopicFilter = filters[ i ];
- * unsubscribeList[ i ].topicFilterLength = strlen( filters[ i ] );
- *
- * // The QoS field of MQTT_SubscribeInfo_t is unused for unsubscribing.
- * }
- *
- * // Obtain a new packet id for the unsubscribe request.
- * packetId = MQTT_GetPacketId( pContext );
- *
- * status = MQTT_Unsubscribe( pContext, &unsubscribeList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, packetId );
- *
- * if( status == MQTTSuccess )
- * {
- * // We must now call MQTT_ReceiveLoop() or MQTT_ProcessLoop() to receive the UNSUBACK.
- * // After this the broker should no longer send publishes for these topics.
- * }
- * @endcode
- */
-/* @[declare_mqtt_unsubscribe] */
-MQTTStatus_t MQTT_Unsubscribe( MQTTContext_t * pContext,
- const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId );
-/* @[declare_mqtt_unsubscribe] */
-
-/**
- * @brief Disconnect an MQTT session.
- *
- * @param[in] pContext Initialized and connected MQTT context.
- *
- * @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to
- * hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSendFailed if transport send failed;
- * #MQTTSuccess otherwise.
- */
-/* @[declare_mqtt_disconnect] */
-MQTTStatus_t MQTT_Disconnect( MQTTContext_t * pContext );
-/* @[declare_mqtt_disconnect] */
-
-/**
- * @brief Loop to receive packets from the transport interface. Handles keep
- * alive.
- *
- * @note If a dummy timer function, #MQTTGetCurrentTimeFunc_t, is passed to the library,
- * then the keep-alive mechanism is not supported by the #MQTT_ProcessLoop API.
- * In that case, the #MQTT_ReceiveLoop API function should be used instead.
- *
- * @param[in] pContext Initialized and connected MQTT context.
- *
- * @note Calling this function blocks the calling context for a time period that
- * depends on the passed the configuration macros, #MQTT_RECV_POLLING_TIMEOUT_MS
- * and #MQTT_SEND_TIMEOUT_MS, and the underlying transport interface implementation
- * timeouts, unless an error occurs. The blocking period also depends on the execution time of the
- * #MQTTEventCallback_t callback supplied to the library. It is recommended that the supplied
- * #MQTTEventCallback_t callback does not contain blocking operations to prevent potential
- * non-deterministic blocking period of the #MQTT_ProcessLoop API call.
- *
- * @return #MQTTBadParameter if context is NULL;
- * #MQTTRecvFailed if a network error occurs during reception;
- * #MQTTSendFailed if a network error occurs while sending an ACK or PINGREQ;
- * #MQTTBadResponse if an invalid packet is received;
- * #MQTTKeepAliveTimeout if the server has not sent a PINGRESP before
- * #MQTT_PINGRESP_TIMEOUT_MS milliseconds;
- * #MQTTIllegalState if an incoming QoS 1/2 publish or ack causes an
- * invalid transition for the internal state machine;
- * #MQTTNeedMoreBytes if MQTT_ProcessLoop has received
- * incomplete data; it should be called again (probably after a delay);
- * #MQTTSuccess on success.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * // This context is assumed to be initialized and connected.
- * MQTTContext_t * pContext;
- *
- * while( true )
- * {
- * status = MQTT_ProcessLoop( pContext );
- *
- * if( status != MQTTSuccess && status != MQTTNeedMoreBytes )
- * {
- * // Determine the error. It's possible we might need to disconnect
- * // the underlying transport connection.
- * }
- * else
- * {
- * // Other application functions.
- * }
- * }
- * @endcode
- */
-/* @[declare_mqtt_processloop] */
-MQTTStatus_t MQTT_ProcessLoop( MQTTContext_t * pContext );
-/* @[declare_mqtt_processloop] */
-
-/**
- * @brief Loop to receive packets from the transport interface. Does not handle
- * keep alive.
- *
- * @note If a dummy #MQTTGetCurrentTimeFunc_t was passed to #MQTT_Init, then the
- * #MQTT_RECV_POLLING_TIMEOUT_MS and #MQTT_SEND_TIMEOUT_MS timeout configurations
- * MUST be set to 0.
- *
- * @param[in] pContext Initialized and connected MQTT context.
- *
- * @note Calling this function blocks the calling context for a time period that
- * depends on the the configuration macros, #MQTT_RECV_POLLING_TIMEOUT_MS and
- * #MQTT_SEND_TIMEOUT_MS, and the underlying transport interface implementation
- * timeouts, unless an error occurs. The blocking period also depends on the execution time of the
- * #MQTTEventCallback_t callback supplied to the library. It is recommended that the supplied
- * #MQTTEventCallback_t callback does not contain blocking operations to prevent potential
- * non-deterministic blocking period of the #MQTT_ReceiveLoop API call.
- *
- * @return #MQTTBadParameter if context is NULL;
- * #MQTTRecvFailed if a network error occurs during reception;
- * #MQTTSendFailed if a network error occurs while sending an ACK or PINGREQ;
- * #MQTTBadResponse if an invalid packet is received;
- * #MQTTIllegalState if an incoming QoS 1/2 publish or ack causes an
- * invalid transition for the internal state machine;
- * #MQTTNeedMoreBytes if MQTT_ReceiveLoop has received
- * incomplete data; it should be called again (probably after a delay);
- * #MQTTSuccess on success.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * uint32_t keepAliveMs = 60 * 1000;
- * // This context is assumed to be initialized and connected.
- * MQTTContext_t * pContext;
- *
- * while( true )
- * {
- * status = MQTT_ReceiveLoop( pContext );
- *
- * if( status != MQTTSuccess && status != MQTTNeedMoreBytes )
- * {
- * // Determine the error. It's possible we might need to disconnect
- * // the underlying transport connection.
- * }
- * else
- * {
- * // Since this function does not send pings, the application may need
- * // to in order to comply with keep alive.
- * if( ( pContext->getTime() - pContext->lastPacketTxTime ) > keepAliveMs )
- * {
- * status = MQTT_Ping( pContext );
- * }
- *
- * // Other application functions.
- * }
- * }
- * @endcode
- */
-/* @[declare_mqtt_receiveloop] */
-MQTTStatus_t MQTT_ReceiveLoop( MQTTContext_t * pContext );
-/* @[declare_mqtt_receiveloop] */
-
-/**
- * @brief Get a packet ID that is valid according to the MQTT 3.1.1 spec.
- *
- * @param[in] pContext Initialized MQTT context.
- *
- * @return A non-zero number.
- */
-/* @[declare_mqtt_getpacketid] */
-uint16_t MQTT_GetPacketId( MQTTContext_t * pContext );
-/* @[declare_mqtt_getpacketid] */
-
-/**
- * @brief A utility function that determines whether the passed topic filter and
- * topic name match according to the MQTT 3.1.1 protocol specification.
- *
- * @param[in] pTopicName The topic name to check.
- * @param[in] topicNameLength Length of the topic name.
- * @param[in] pTopicFilter The topic filter to check.
- * @param[in] topicFilterLength Length of topic filter.
- * @param[out] pIsMatch If the match is performed without any error, that is if the
- * return value is MQTTSuccess, then and only then the value in this parameter is valid
- * and updated. In such a case, if the topic filter and the topic name match, then this
- * value is set to true; otherwise if there is no match then it is set to false.
- *
- * @note The API assumes that the passed topic name is valid to meet the
- * requirements of the MQTT 3.1.1 specification. Invalid topic names (for example,
- * containing wildcard characters) should not be passed to the function.
- * Also, the API checks validity of topic filter for wildcard characters ONLY if
- * the passed topic name and topic filter do not have an exact string match.
- *
- * @return Returns one of the following:
- * - #MQTTBadParameter, if any of the input parameters is invalid.
- * - #MQTTSuccess, if the matching operation was performed.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * const char * pTopic = "topic/match/1";
- * const char * pFilter = "topic/#";
- * MQTTStatus_t status = MQTTSuccess;
- * bool match = false;
- *
- * status = MQTT_MatchTopic( pTopic, strlen( pTopic ), pFilter, strlen( pFilter ), &match );
- * // Our parameters were valid, so this will return success.
- * assert( status == MQTTSuccess );
- *
- * // For this specific example, we already know this value is true. This
- * // check is placed here as an example for use with variable topic names.
- * if( match )
- * {
- * // Application can decide what to do with the matching topic name.
- * }
- * @endcode
- */
-MQTTStatus_t MQTT_MatchTopic( const char * pTopicName,
- const uint16_t topicNameLength,
- const char * pTopicFilter,
- const uint16_t topicFilterLength,
- bool * pIsMatch );
-
-/**
- * @brief Parses the payload of an MQTT SUBACK packet that contains status codes
- * corresponding to topic filter subscription requests from the original
- * subscribe packet.
- *
- * Each return code in the SUBACK packet corresponds to a topic filter in the
- * SUBSCRIBE Packet being acknowledged.
- * The status codes can be one of the following:
- * - 0x00 - Success - Maximum QoS 0
- * - 0x01 - Success - Maximum QoS 1
- * - 0x02 - Success - Maximum QoS 2
- * - 0x80 - Failure
- * Refer to #MQTTSubAckStatus_t for the status codes.
- *
- * @param[in] pSubackPacket The SUBACK packet whose payload is to be parsed.
- * @param[out] pPayloadStart This is populated with the starting address
- * of the payload (or return codes for topic filters) in the SUBACK packet.
- * @param[out] pPayloadSize This is populated with the size of the payload
- * in the SUBACK packet. It represents the number of topic filters whose
- * SUBACK status is present in the packet.
- *
- * @return Returns one of the following:
- * - #MQTTBadParameter if the input SUBACK packet is invalid.
- * - #MQTTSuccess if parsing the payload was successful.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Global variable used in this example.
- * // This is assumed to be the subscription list in the original SUBSCRIBE packet.
- * MQTTSubscribeInfo_t pSubscribes[ NUMBER_OF_SUBSCRIPTIONS ];
- *
- * // MQTT_GetSubAckStatusCodes is intended to be used from the application
- * // callback that is called by the library in MQTT_ProcessLoop or MQTT_ReceiveLoop.
- * void eventCallback(
- * MQTTContext_t * pContext,
- * MQTTPacketInfo_t * pPacketInfo,
- * MQTTDeserializedInfo_t * pDeserializedInfo
- * )
- * {
- * MQTTStatus_t status = MQTTSuccess;
- * uint8_t * pCodes;
- * size_t numCodes;
- *
- * if( pPacketInfo->type == MQTT_PACKET_TYPE_SUBACK )
- * {
- * status = MQTT_GetSubAckStatusCodes( pPacketInfo, &pCodes, &numCodes );
- *
- * // Since the pointers to the payload and payload size are not NULL, and
- * // we use the packet info struct passed to the app callback (verified
- * // to be valid by the library), this function must return success.
- * assert( status == MQTTSuccess );
- * // The server must send a response code for each topic filter in the
- * // original SUBSCRIBE packet.
- * assert( numCodes == NUMBER_OF_SUBSCRIPTIONS );
- *
- * for( int i = 0; i < numCodes; i++ )
- * {
- * // The only failure code is 0x80 = MQTTSubAckFailure.
- * if( pCodes[ i ] == MQTTSubAckFailure )
- * {
- * // The subscription failed, we may want to retry the
- * // subscription in pSubscribes[ i ] outside of this callback.
- * }
- * else
- * {
- * // The subscription was granted, but the maximum QoS may be
- * // lower than what was requested. We can verify the granted QoS.
- * if( pSubscribes[ i ].qos != pCodes[ i ] )
- * {
- * LogWarn( (
- * "Requested QoS %u, but granted QoS %u for %s",
- * pSubscribes[ i ].qos, pCodes[ i ], pSubscribes[ i ].pTopicFilter
- * ) );
- * }
- * }
- * }
- * }
- * // Handle other packet types.
- * }
- * @endcode
- */
-/* @[declare_mqtt_getsubackstatuscodes] */
-MQTTStatus_t MQTT_GetSubAckStatusCodes( const MQTTPacketInfo_t * pSubackPacket,
- uint8_t ** pPayloadStart,
- size_t * pPayloadSize );
-/* @[declare_mqtt_getsubackstatuscodes] */
-
-/**
- * @brief Error code to string conversion for MQTT statuses.
- *
- * @param[in] status The status to convert to a string.
- *
- * @return The string representation of the status.
- */
-/* @[declare_mqtt_status_strerror] */
-const char * MQTT_Status_strerror( MQTTStatus_t status );
-/* @[declare_mqtt_status_strerror] */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_MQTT_H */
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_config.h b/project/coreMQTT/coreMQTT/core_mqtt_config.h
deleted file mode 120000
index 502a507..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_config.h
+++ /dev/null
@@ -1 +0,0 @@
-core_mqtt_config_defaults.h
\ No newline at end of file
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_config_defaults.h b/project/coreMQTT/coreMQTT/core_mqtt_config_defaults.h
deleted file mode 100644
index 35b42d5..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_config_defaults.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt_config_defaults.h
- * @brief This represents the default values for the configuration macros
- * for the MQTT library.
- *
- * @note This file SHOULD NOT be modified. If custom values are needed for
- * any configuration macro, a core_mqtt_config.h file should be provided to
- * the MQTT library to override the default values defined in this file.
- * To use the custom config file, the MQTT_DO_NOT_USE_CUSTOM_CONFIG preprocessor
- * macro SHOULD NOT be set.
- */
-
-#ifndef CORE_MQTT_CONFIG_DEFAULTS_H_
-#define CORE_MQTT_CONFIG_DEFAULTS_H_
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/* MQTT_DO_NOT_USE_CUSTOM_CONFIG allows building the MQTT library
- * without a custom config. If a custom config is provided, the
- * MQTT_DO_NOT_USE_CUSTOM_CONFIG macro should not be defined. */
-#ifndef MQTT_DO_NOT_USE_CUSTOM_CONFIG
-/* Include custom config file before other headers. */
- #include "core_mqtt_config.h"
-#endif
-
-/* The macro definition for MQTT_DO_NOT_USE_CUSTOM_CONFIG is for Doxygen
- * documentation only. */
-
-/**
- * @brief Define this macro to build the MQTT library without the custom config
- * file core_mqtt_config.h.
- *
- * Without the custom config, the MQTT library builds with
- * default values of config macros defined in core_mqtt_config_defaults.h file.
- *
- * If a custom config is provided, then MQTT_DO_NOT_USE_CUSTOM_CONFIG should not
- * be defined.
- */
-#ifdef DOXYGEN
- #define MQTT_DO_NOT_USE_CUSTOM_CONFIG
-#endif
-
-/**
- * @ingroup mqtt_constants
- * @brief Maximum number of vectors in subscribe and unsubscribe packet.
- */
-#ifndef MQTT_SUB_UNSUB_MAX_VECTORS
- #define MQTT_SUB_UNSUB_MAX_VECTORS ( 4U )
-#endif
-
-/**
- * @brief The number of retries for receiving CONNACK.
- *
- * The MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT will be used only when the
- * timeoutMs parameter of #MQTT_Connect is passed as 0 . The transport
- * receive for CONNACK will be retried MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT
- * times before timing out. A value of 0 for this config will cause the
- * transport receive for CONNACK to be invoked only once.
- *
- * <b>Possible values:</b> Any positive 16 bit integer. <br>
- * <b>Default value:</b> `5`
- */
-#ifndef MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT
-/* Default value for the CONNACK receive retries. */
- #define MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT ( 5U )
-#endif
-
-/**
- * @brief Maximum number of milliseconds to wait for a ping response to a ping
- * request as part of the keep-alive mechanism.
- *
- * If a ping response is not received before this timeout, then
- * #MQTT_ProcessLoop will return #MQTTKeepAliveTimeout.
- *
- * @note If this value is more than half of the keep alive interval, and the
- * server does not receive the previous ping request, then it is likely that the
- * server will disconnect the client before #MQTTKeepAliveTimeout can be returned.
- *
- * @note If a dummy implementation of the #MQTTGetCurrentTimeFunc_t timer function,
- * is supplied to the library, then the keep-alive mechanism is not supported by the
- * #MQTT_ProcessLoop API function. In that case, the value of #MQTT_PINGRESP_TIMEOUT_MS
- * is irrelevant to the behavior of the library.
- *
- * <b>Possible values:</b> Any positive integer up to SIZE_MAX. <br>
- * <b>Default value:</b> `5000`
- */
-#ifndef MQTT_PINGRESP_TIMEOUT_MS
-/* Wait 5 seconds by default for a ping response. */
- #define MQTT_PINGRESP_TIMEOUT_MS ( 5000U )
-#endif
-
-/**
- * @brief Maximum number of milliseconds of TX inactivity to wait
- * before initiating a PINGREQ
- *
- * @note If this value is less than the keep alive interval than
- * it will be used instead.
- *
- * <b>Possible values:</b> Any positive integer up to SIZE_MAX. <br>
- * <b>Default value:</b> '30000'
- */
-#ifndef PACKET_TX_TIMEOUT_MS
- #define PACKET_TX_TIMEOUT_MS ( 30000U )
-#endif
-
-/**
- * @brief Maximum number of milliseconds of RX inactivity to wait
- * before initiating a PINGREQ
- *
- * <b>Possible values:</b> Any positive integer up to SIZE_MAX. <br>
- * <b>Default value:</b> '30000'
- *
- */
-#ifndef PACKET_RX_TIMEOUT_MS
- #define PACKET_RX_TIMEOUT_MS ( 30000U )
-#endif
-
-/**
- * @brief The maximum duration between non-empty network reads while
- * receiving an MQTT packet via the #MQTT_ProcessLoop or #MQTT_ReceiveLoop
- * API functions.
- *
- * When an incoming MQTT packet is detected, the transport receive function
- * may be called multiple times until all of the expected number of bytes of the
- * packet are received. This timeout represents the maximum polling duration that
- * is allowed without any data reception from the network for the incoming packet.
- *
- * If the timeout expires, the #MQTT_ProcessLoop and #MQTT_ReceiveLoop functions
- * return #MQTTRecvFailed.
- *
- * @note If a dummy implementation of the #MQTTGetCurrentTimeFunc_t timer function,
- * is supplied to the library, then #MQTT_RECV_POLLING_TIMEOUT_MS MUST be set to 0.
- *
- * <b>Possible values:</b> Any positive 32 bit integer. Recommended to use a
- * small timeout value. <br>
- * <b>Default value:</b> `10`
- *
- */
-#ifndef MQTT_RECV_POLLING_TIMEOUT_MS
- #define MQTT_RECV_POLLING_TIMEOUT_MS ( 10U )
-#endif
-
-/**
- * @brief The maximum duration allowed to send an MQTT packet over the transport
- * interface.
- *
- * When sending an MQTT packet, the transport send or writev functions may be
- * called multiple times until all of the required number of bytes are sent.
- * This timeout represents the maximum duration that is allowed to send the MQTT
- * packet while calling the transport send or writev functions.
- *
- * If the timeout expires, #MQTTSendFailed will be returned by the public API
- * functions.
- *
- * @note If a dummy implementation of the #MQTTGetCurrentTimeFunc_t timer function,
- * is supplied to the library, then #MQTT_SEND_TIMEOUT_MS MUST be set to 0.
- *
- * <b>Possible values:</b> Any positive 32 bit integer. <br>
- * <b>Default value:</b> `20000`
- *
- */
-#ifndef MQTT_SEND_TIMEOUT_MS
- #define MQTT_SEND_TIMEOUT_MS ( 20000U )
-#endif
-
-#ifdef MQTT_SEND_RETRY_TIMEOUT_MS
- #error MQTT_SEND_RETRY_TIMEOUT_MS is deprecated. Instead use MQTT_SEND_TIMEOUT_MS.
-#endif
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_MQTT_CONFIG_DEFAULTS_H_ */
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_default_logging.h b/project/coreMQTT/coreMQTT/core_mqtt_default_logging.h
deleted file mode 100644
index dcacf90..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_default_logging.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt_default_logging.h
- * @brief This represents the default values for the logging macros for the MQTT
- * library.
- *
- * @note This file SHOULD NOT be modified. If custom values are needed for
- * any configuration macro, a core_mqtt_config.h file should be provided to
- * the MQTT library to override the default values defined in this file.
- * To use the custom config file, the MQTT_DO_NOT_USE_CUSTOM_CONFIG preprocessor
- * macro SHOULD NOT be set.
- */
-
-#ifndef CORE_MQTT_DEFAULT_LOGGING_H_
-#define CORE_MQTT_DEFAULT_LOGGING_H_
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/**
- * @brief Macro that is called in the MQTT library for logging "Error" level
- * messages.
- *
- * To enable error level logging in the MQTT library, this macro should be mapped to the
- * application-specific logging implementation that supports error logging.
- *
- * @note This logging macro is called in the MQTT library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_mqtt_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
- *
- * <b>Default value</b>: Error logging is turned off, and no code is generated for calls
- * to the macro in the MQTT library on compilation.
- */
-#ifndef LogError
- #define LogError( message )
-#endif
-
-/**
- * @brief Macro that is called in the MQTT library for logging "Warning" level
- * messages.
- *
- * To enable warning level logging in the MQTT library, this macro should be mapped to the
- * application-specific logging implementation that supports warning logging.
- *
- * @note This logging macro is called in the MQTT library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_mqtt_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/).
- *
- * <b>Default value</b>: Warning logs are turned off, and no code is generated for calls
- * to the macro in the MQTT library on compilation.
- */
-#ifndef LogWarn
- #define LogWarn( message )
-#endif
-
-/**
- * @brief Macro that is called in the MQTT library for logging "Info" level
- * messages.
- *
- * To enable info level logging in the MQTT library, this macro should be mapped to the
- * application-specific logging implementation that supports info logging.
- *
- * @note This logging macro is called in the MQTT library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_mqtt_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/).
- *
- * <b>Default value</b>: Info logging is turned off, and no code is generated for calls
- * to the macro in the MQTT library on compilation.
- */
-#ifndef LogInfo
- #define LogInfo( message )
-#endif
-
-/**
- * @brief Macro that is called in the MQTT library for logging "Debug" level
- * messages.
- *
- * To enable debug level logging from MQTT library, this macro should be mapped to the
- * application-specific logging implementation that supports debug logging.
- *
- * @note This logging macro is called in the MQTT library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_mqtt_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/).
- *
- * <b>Default value</b>: Debug logging is turned off, and no code is generated for calls
- * to the macro in the MQTT library on compilation.
- */
-#ifndef LogDebug
- #define LogDebug( message )
-#endif
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_MQTT_DEFAULT_LOGGING_H_ */
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_serializer.c b/project/coreMQTT/coreMQTT/core_mqtt_serializer.c
deleted file mode 100644
index 3e2b427..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_serializer.c
+++ /dev/null
@@ -1,2684 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt_serializer.c
- * @brief Implements the user-facing functions in core_mqtt_serializer.h.
- */
-#include <string.h>
-#include <assert.h>
-
-#include "core_mqtt_serializer.h"
-
-/* Include config defaults header to get default values of configs. */
-#include "core_mqtt_config_defaults.h"
-
-#include "core_mqtt_default_logging.h"
-
-/**
- * @brief MQTT protocol version 3.1.1.
- */
-#define MQTT_VERSION_3_1_1 ( ( uint8_t ) 4U )
-
-/**
- * @brief Size of the fixed and variable header of a CONNECT packet.
- */
-#define MQTT_PACKET_CONNECT_HEADER_SIZE ( 10UL )
-
-/* MQTT CONNECT flags. */
-#define MQTT_CONNECT_FLAG_CLEAN ( 1 ) /**< @brief Clean session. */
-#define MQTT_CONNECT_FLAG_WILL ( 2 ) /**< @brief Will present. */
-#define MQTT_CONNECT_FLAG_WILL_QOS1 ( 3 ) /**< @brief Will QoS 1. */
-#define MQTT_CONNECT_FLAG_WILL_QOS2 ( 4 ) /**< @brief Will QoS 2. */
-#define MQTT_CONNECT_FLAG_WILL_RETAIN ( 5 ) /**< @brief Will retain. */
-#define MQTT_CONNECT_FLAG_PASSWORD ( 6 ) /**< @brief Password present. */
-#define MQTT_CONNECT_FLAG_USERNAME ( 7 ) /**< @brief User name present. */
-
-/*
- * Positions of each flag in the first byte of an MQTT PUBLISH packet's
- * fixed header.
- */
-#define MQTT_PUBLISH_FLAG_RETAIN ( 0 ) /**< @brief MQTT PUBLISH retain flag. */
-#define MQTT_PUBLISH_FLAG_QOS1 ( 1 ) /**< @brief MQTT PUBLISH QoS1 flag. */
-#define MQTT_PUBLISH_FLAG_QOS2 ( 2 ) /**< @brief MQTT PUBLISH QoS2 flag. */
-#define MQTT_PUBLISH_FLAG_DUP ( 3 ) /**< @brief MQTT PUBLISH duplicate flag. */
-
-/**
- * @brief The size of MQTT DISCONNECT packets, per MQTT spec.
- */
-#define MQTT_DISCONNECT_PACKET_SIZE ( 2UL )
-
-/**
- * @brief A PINGREQ packet is always 2 bytes in size, defined by MQTT 3.1.1 spec.
- */
-#define MQTT_PACKET_PINGREQ_SIZE ( 2UL )
-
-/**
- * @brief The Remaining Length field of MQTT disconnect packets, per MQTT spec.
- */
-#define MQTT_DISCONNECT_REMAINING_LENGTH ( ( uint8_t ) 0 )
-
-/*
- * Constants relating to CONNACK packets, defined by MQTT 3.1.1 spec.
- */
-#define MQTT_PACKET_CONNACK_REMAINING_LENGTH ( ( uint8_t ) 2U ) /**< @brief A CONNACK packet always has a "Remaining length" of 2. */
-#define MQTT_PACKET_CONNACK_SESSION_PRESENT_MASK ( ( uint8_t ) 0x01U ) /**< @brief The "Session Present" bit is always the lowest bit. */
-
-/*
- * UNSUBACK, PUBACK, PUBREC, PUBREL, and PUBCOMP always have a remaining length
- * of 2.
- */
-#define MQTT_PACKET_SIMPLE_ACK_REMAINING_LENGTH ( ( uint8_t ) 2 ) /**< @brief PUBACK, PUBREC, PUBREl, PUBCOMP, UNSUBACK Remaining length. */
-#define MQTT_PACKET_PINGRESP_REMAINING_LENGTH ( 0U ) /**< @brief A PINGRESP packet always has a "Remaining length" of 0. */
-
-/**
- * @brief Per the MQTT 3.1.1 spec, the largest "Remaining Length" of an MQTT
- * packet is this value, 256 MB.
- */
-#define MQTT_MAX_REMAINING_LENGTH ( 268435455UL )
-
-/**
- * @brief Set a bit in an 8-bit unsigned integer.
- */
-#define UINT8_SET_BIT( x, position ) ( ( x ) = ( uint8_t ) ( ( x ) | ( 0x01U << ( position ) ) ) )
-
-/**
- * @brief Macro for checking if a bit is set in a 1-byte unsigned int.
- *
- * @param[in] x The unsigned int to check.
- * @param[in] position Which bit to check.
- */
-#define UINT8_CHECK_BIT( x, position ) ( ( ( x ) & ( 0x01U << ( position ) ) ) == ( 0x01U << ( position ) ) )
-
-/**
- * @brief Get the high byte of a 16-bit unsigned integer.
- */
-#define UINT16_HIGH_BYTE( x ) ( ( uint8_t ) ( ( x ) >> 8 ) )
-
-/**
- * @brief Get the low byte of a 16-bit unsigned integer.
- */
-#define UINT16_LOW_BYTE( x ) ( ( uint8_t ) ( ( x ) & 0x00ffU ) )
-
-/**
- * @brief Macro for decoding a 2-byte unsigned int from a sequence of bytes.
- *
- * @param[in] ptr A uint8_t* that points to the high byte.
- */
-#define UINT16_DECODE( ptr ) \
- ( uint16_t ) ( ( ( ( uint16_t ) ptr[ 0 ] ) << 8 ) | \
- ( ( uint16_t ) ptr[ 1 ] ) )
-
-/**
- * @brief A value that represents an invalid remaining length.
- *
- * This value is greater than what is allowed by the MQTT specification.
- */
-#define MQTT_REMAINING_LENGTH_INVALID ( ( size_t ) 268435456 )
-
-/**
- * @brief The minimum remaining length for a QoS 0 PUBLISH.
- *
- * Includes two bytes for topic name length and one byte for topic name.
- */
-#define MQTT_MIN_PUBLISH_REMAINING_LENGTH_QOS0 ( 3U )
-
-/*-----------------------------------------------------------*/
-
-
-/**
- * @brief MQTT Subscription packet types.
- */
-typedef enum MQTTSubscriptionType
-{
- MQTT_SUBSCRIBE, /**< @brief The type is a SUBSCRIBE packet. */
- MQTT_UNSUBSCRIBE /**< @brief The type is a UNSUBSCRIBE packet. */
-} MQTTSubscriptionType_t;
-
-/*-----------------------------------------------------------*/
-
-/**
- * @brief Serializes MQTT PUBLISH packet into the buffer provided.
- *
- * This function serializes MQTT PUBLISH packet into #MQTTFixedBuffer_t.pBuffer.
- * Copy of the payload into the buffer is done as part of the serialization
- * only if @p serializePayload is true.
- *
- * @brief param[in] pPublishInfo Publish information.
- * @brief param[in] remainingLength Remaining length of the PUBLISH packet.
- * @brief param[in] packetIdentifier Packet identifier of PUBLISH packet.
- * @brief param[in, out] pFixedBuffer Buffer to which PUBLISH packet will be
- * serialized.
- * @brief param[in] serializePayload Copy payload to the serialized buffer
- * only if true. Only PUBLISH header will be serialized if false.
- *
- * @return Total number of bytes sent; -1 if there is an error.
- */
-static void serializePublishCommon( const MQTTPublishInfo_t * pPublishInfo,
- size_t remainingLength,
- uint16_t packetIdentifier,
- const MQTTFixedBuffer_t * pFixedBuffer,
- bool serializePayload );
-
-/**
- * @brief Calculates the packet size and remaining length of an MQTT
- * PUBLISH packet.
- *
- * @param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @param[out] pRemainingLength The Remaining Length of the MQTT PUBLISH packet.
- * @param[out] pPacketSize The total size of the MQTT PUBLISH packet.
- *
- * @return false if the packet would exceed the size allowed by the
- * MQTT spec; true otherwise.
- */
-static bool calculatePublishPacketSize( const MQTTPublishInfo_t * pPublishInfo,
- size_t * pRemainingLength,
- size_t * pPacketSize );
-
-/**
- * @brief Calculates the packet size and remaining length of an MQTT
- * SUBSCRIBE or UNSUBSCRIBE packet.
- *
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[out] pRemainingLength The Remaining Length of the MQTT SUBSCRIBE or
- * UNSUBSCRIBE packet.
- * @param[out] pPacketSize The total size of the MQTT MQTT SUBSCRIBE or
- * UNSUBSCRIBE packet.
- * @param[in] subscriptionType #MQTT_SUBSCRIBE or #MQTT_UNSUBSCRIBE.
- *
- * #MQTTBadParameter if the packet would exceed the size allowed by the
- * MQTT spec or a subscription is empty; #MQTTSuccess otherwise.
- */
-static MQTTStatus_t calculateSubscriptionPacketSize( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- size_t * pRemainingLength,
- size_t * pPacketSize,
- MQTTSubscriptionType_t subscriptionType );
-
-/**
- * @brief Validates parameters of #MQTT_SerializeSubscribe or
- * #MQTT_SerializeUnsubscribe.
- *
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[in] packetId Packet identifier.
- * @param[in] remainingLength Remaining length of the packet.
- * @param[in] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- */
-static MQTTStatus_t validateSubscriptionSerializeParams( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer );
-
-/**
- * @brief Serialize an MQTT CONNECT packet in the given buffer.
- *
- * @param[in] pConnectInfo MQTT CONNECT packet parameters.
- * @param[in] pWillInfo Last Will and Testament. Pass NULL if not used.
- * @param[in] remainingLength Remaining Length of MQTT CONNECT packet.
- * @param[out] pFixedBuffer Buffer for packet serialization.
- */
-static void serializeConnectPacket( const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer );
-
-/**
- * @brief Prints the appropriate message for the CONNACK response code if logs
- * are enabled.
- *
- * @param[in] responseCode MQTT standard CONNACK response code.
- */
-static void logConnackResponse( uint8_t responseCode );
-
-/**
- * @brief Encodes the remaining length of the packet using the variable length
- * encoding scheme provided in the MQTT v3.1.1 specification.
- *
- * @param[out] pDestination The destination buffer to store the encoded remaining
- * length.
- * @param[in] length The remaining length to encode.
- *
- * @return The location of the byte following the encoded value.
- */
-static uint8_t * encodeRemainingLength( uint8_t * pDestination,
- size_t length );
-
-/**
- * @brief Retrieve the size of the remaining length if it were to be encoded.
- *
- * @param[in] length The remaining length to be encoded.
- *
- * @return The size of the remaining length if it were to be encoded.
- */
-static size_t remainingLengthEncodedSize( size_t length );
-
-/**
- * @brief Encode a string whose size is at maximum 16 bits in length.
- *
- * @param[out] pDestination Destination buffer for the encoding.
- * @param[in] pSource The source string to encode.
- * @param[in] sourceLength The length of the source string to encode.
- *
- * @return A pointer to the end of the encoded string.
- */
-static uint8_t * encodeString( uint8_t * pDestination,
- const char * pSource,
- uint16_t sourceLength );
-
-/**
- * @brief Retrieves and decodes the Remaining Length from the network interface
- * by reading a single byte at a time.
- *
- * @param[in] recvFunc Network interface receive function.
- * @param[in] pNetworkContext Network interface context to the receive function.
- *
- * @return The Remaining Length of the incoming packet.
- */
-static size_t getRemainingLength( TransportRecv_t recvFunc,
- NetworkContext_t * pNetworkContext );
-
-/**
- * @brief Retrieves, decodes and stores the Remaining Length from the network
- * interface by reading a single byte at a time.
- *
- * @param[in] pBuffer The buffer holding the raw data to be processed
- * @param[in] pIndex Pointer to the index within the buffer to marking the end of raw data
- * available.
- * @param[in] pIncomingPacket Structure used to hold the fields of the
- * incoming packet.
- *
- * @return MQTTNeedMoreBytes is returned to show that the incoming
- * packet is not yet fully received and decoded. Otherwise, MQTTSuccess
- * shows that processing of the packet was successful.
- */
-static MQTTStatus_t processRemainingLength( const uint8_t * pBuffer,
- const size_t * pIndex,
- MQTTPacketInfo_t * pIncomingPacket );
-
-/**
- * @brief Check if an incoming packet type is valid.
- *
- * @param[in] packetType The packet type to check.
- *
- * @return `true` if the packet type is valid; `false` otherwise.
- */
-static bool incomingPacketValid( uint8_t packetType );
-
-/**
- * @brief Check the remaining length of an incoming PUBLISH packet against some
- * value for QoS 0, or for QoS 1 and 2.
- *
- * The remaining length for a QoS 1 and 2 packet will always be two greater than
- * for a QoS 0.
- *
- * @param[in] remainingLength Remaining length of the PUBLISH packet.
- * @param[in] qos The QoS of the PUBLISH.
- * @param[in] qos0Minimum Minimum possible remaining length for a QoS 0 PUBLISH.
- *
- * @return #MQTTSuccess or #MQTTBadResponse.
- */
-static MQTTStatus_t checkPublishRemainingLength( size_t remainingLength,
- MQTTQoS_t qos,
- size_t qos0Minimum );
-
-/**
- * @brief Process the flags of an incoming PUBLISH packet.
- *
- * @param[in] publishFlags Flags of an incoming PUBLISH.
- * @param[in, out] pPublishInfo Pointer to #MQTTPublishInfo_t struct where
- * output will be written.
- *
- * @return #MQTTSuccess or #MQTTBadResponse.
- */
-static MQTTStatus_t processPublishFlags( uint8_t publishFlags,
- MQTTPublishInfo_t * pPublishInfo );
-
-/**
- * @brief Deserialize a CONNACK packet.
- *
- * Converts the packet from a stream of bytes to an #MQTTStatus_t.
- *
- * @param[in] pConnack Pointer to an MQTT packet struct representing a
- * CONNACK.
- * @param[out] pSessionPresent Whether a previous session was present.
- *
- * @return #MQTTSuccess if CONNACK specifies that CONNECT was accepted;
- * #MQTTServerRefused if CONNACK specifies that CONNECT was rejected;
- * #MQTTBadResponse if the CONNACK packet doesn't follow MQTT spec.
- */
-static MQTTStatus_t deserializeConnack( const MQTTPacketInfo_t * pConnack,
- bool * pSessionPresent );
-
-/**
- * @brief Decode the status bytes of a SUBACK packet to a #MQTTStatus_t.
- *
- * @param[in] statusCount Number of status bytes in the SUBACK.
- * @param[in] pStatusStart The first status byte in the SUBACK.
- *
- * @return #MQTTSuccess, #MQTTServerRefused, or #MQTTBadResponse.
- */
-static MQTTStatus_t readSubackStatus( size_t statusCount,
- const uint8_t * pStatusStart );
-
-/**
- * @brief Deserialize a SUBACK packet.
- *
- * Converts the packet from a stream of bytes to an #MQTTStatus_t and extracts
- * the packet identifier.
- *
- * @param[in] pSuback Pointer to an MQTT packet struct representing a SUBACK.
- * @param[out] pPacketIdentifier Packet ID of the SUBACK.
- *
- * @return #MQTTSuccess if SUBACK is valid; #MQTTBadResponse if SUBACK packet
- * doesn't follow the MQTT spec.
- */
-static MQTTStatus_t deserializeSuback( const MQTTPacketInfo_t * pSuback,
- uint16_t * pPacketIdentifier );
-
-/**
- * @brief Deserialize a PUBLISH packet received from the server.
- *
- * Converts the packet from a stream of bytes to an #MQTTPublishInfo_t and
- * extracts the packet identifier. Also prints out debug log messages about the
- * packet.
- *
- * @param[in] pIncomingPacket Pointer to an MQTT packet struct representing a
- * PUBLISH.
- * @param[out] pPacketId Packet identifier of the PUBLISH.
- * @param[out] pPublishInfo Pointer to #MQTTPublishInfo_t where output is
- * written.
- *
- * @return #MQTTSuccess if PUBLISH is valid; #MQTTBadResponse
- * if the PUBLISH packet doesn't follow MQTT spec.
- */
-static MQTTStatus_t deserializePublish( const MQTTPacketInfo_t * pIncomingPacket,
- uint16_t * pPacketId,
- MQTTPublishInfo_t * pPublishInfo );
-
-/**
- * @brief Deserialize an UNSUBACK, PUBACK, PUBREC, PUBREL, or PUBCOMP packet.
- *
- * Converts the packet from a stream of bytes to an #MQTTStatus_t and extracts
- * the packet identifier.
- *
- * @param[in] pAck Pointer to the MQTT packet structure representing the packet.
- * @param[out] pPacketIdentifier Packet ID of the ack type packet.
- *
- * @return #MQTTSuccess if UNSUBACK, PUBACK, PUBREC, PUBREL, or PUBCOMP is valid;
- * #MQTTBadResponse if the packet doesn't follow the MQTT spec.
- */
-static MQTTStatus_t deserializeSimpleAck( const MQTTPacketInfo_t * pAck,
- uint16_t * pPacketIdentifier );
-
-/**
- * @brief Deserialize a PINGRESP packet.
- *
- * Converts the packet from a stream of bytes to an #MQTTStatus_t.
- *
- * @param[in] pPingresp Pointer to an MQTT packet struct representing a PINGRESP.
- *
- * @return #MQTTSuccess if PINGRESP is valid; #MQTTBadResponse if the PINGRESP
- * packet doesn't follow MQTT spec.
- */
-static MQTTStatus_t deserializePingresp( const MQTTPacketInfo_t * pPingresp );
-
-/*-----------------------------------------------------------*/
-
-static size_t remainingLengthEncodedSize( size_t length )
-{
- size_t encodedSize;
-
- /* Determine how many bytes are needed to encode length.
- * The values below are taken from the MQTT 3.1.1 spec. */
-
- /* 1 byte is needed to encode lengths between 0 and 127. */
- if( length < 128U )
- {
- encodedSize = 1U;
- }
- /* 2 bytes are needed to encode lengths between 128 and 16,383. */
- else if( length < 16384U )
- {
- encodedSize = 2U;
- }
- /* 3 bytes are needed to encode lengths between 16,384 and 2,097,151. */
- else if( length < 2097152U )
- {
- encodedSize = 3U;
- }
- /* 4 bytes are needed to encode lengths between 2,097,152 and 268,435,455. */
- else
- {
- encodedSize = 4U;
- }
-
- LogDebug( ( "Encoded size for length %lu is %lu bytes.",
- ( unsigned long ) length,
- ( unsigned long ) encodedSize ) );
-
- return encodedSize;
-}
-
-/*-----------------------------------------------------------*/
-
-static uint8_t * encodeRemainingLength( uint8_t * pDestination,
- size_t length )
-{
- uint8_t lengthByte;
- uint8_t * pLengthEnd = NULL;
- size_t remainingLength = length;
-
- assert( pDestination != NULL );
-
- pLengthEnd = pDestination;
-
- /* This algorithm is copied from the MQTT v3.1.1 spec. */
- do
- {
- lengthByte = ( uint8_t ) ( remainingLength % 128U );
- remainingLength = remainingLength / 128U;
-
- /* Set the high bit of this byte, indicating that there's more data. */
- if( remainingLength > 0U )
- {
- UINT8_SET_BIT( lengthByte, 7 );
- }
-
- /* Output a single encoded byte. */
- *pLengthEnd = lengthByte;
- pLengthEnd++;
- } while( remainingLength > 0U );
-
- return pLengthEnd;
-}
-
-/*-----------------------------------------------------------*/
-
-static uint8_t * encodeString( uint8_t * pDestination,
- const char * pSource,
- uint16_t sourceLength )
-{
- uint8_t * pBuffer = NULL;
-
- /* Typecast const char * typed source buffer to const uint8_t *.
- * This is to use same type buffers in memcpy. */
- const uint8_t * pSourceBuffer = ( const uint8_t * ) pSource;
-
- assert( pDestination != NULL );
-
- pBuffer = pDestination;
-
- /* The first byte of a UTF-8 string is the high byte of the string length. */
- *pBuffer = UINT16_HIGH_BYTE( sourceLength );
- pBuffer++;
-
- /* The second byte of a UTF-8 string is the low byte of the string length. */
- *pBuffer = UINT16_LOW_BYTE( sourceLength );
- pBuffer++;
-
- /* Copy the string into pBuffer. */
- if( pSourceBuffer != NULL )
- {
- ( void ) memcpy( pBuffer, pSourceBuffer, sourceLength );
- }
-
- /* Return the pointer to the end of the encoded string. */
- pBuffer = &pBuffer[ sourceLength ];
-
- return pBuffer;
-}
-
-/*-----------------------------------------------------------*/
-
-static bool calculatePublishPacketSize( const MQTTPublishInfo_t * pPublishInfo,
- size_t * pRemainingLength,
- size_t * pPacketSize )
-{
- bool status = true;
- size_t packetSize = 0, payloadLimit = 0;
-
- assert( pPublishInfo != NULL );
- assert( pRemainingLength != NULL );
- assert( pPacketSize != NULL );
-
- /* The variable header of a PUBLISH packet always contains the topic name.
- * The first 2 bytes of UTF-8 string contains length of the string.
- */
- packetSize += pPublishInfo->topicNameLength + sizeof( uint16_t );
-
- /* The variable header of a QoS 1 or 2 PUBLISH packet contains a 2-byte
- * packet identifier. */
- if( pPublishInfo->qos > MQTTQoS0 )
- {
- packetSize += sizeof( uint16_t );
- }
-
- /* Calculate the maximum allowed size of the payload for the given parameters.
- * This calculation excludes the "Remaining length" encoding, whose size is not
- * yet known. */
- payloadLimit = MQTT_MAX_REMAINING_LENGTH - packetSize - 1U;
-
- /* Ensure that the given payload fits within the calculated limit. */
- if( pPublishInfo->payloadLength > payloadLimit )
- {
- LogError( ( "PUBLISH payload length of %lu cannot exceed "
- "%lu so as not to exceed the maximum "
- "remaining length of MQTT 3.1.1 packet( %lu ).",
- ( unsigned long ) pPublishInfo->payloadLength,
- ( unsigned long ) payloadLimit,
- MQTT_MAX_REMAINING_LENGTH ) );
- status = false;
- }
- else
- {
- /* Add the length of the PUBLISH payload. At this point, the "Remaining length"
- * has been calculated. */
- packetSize += pPublishInfo->payloadLength;
-
- /* Now that the "Remaining length" is known, recalculate the payload limit
- * based on the size of its encoding. */
- payloadLimit -= remainingLengthEncodedSize( packetSize );
-
- /* Check that the given payload fits within the size allowed by MQTT spec. */
- if( pPublishInfo->payloadLength > payloadLimit )
- {
- LogError( ( "PUBLISH payload length of %lu cannot exceed "
- "%lu so as not to exceed the maximum "
- "remaining length of MQTT 3.1.1 packet( %lu ).",
- ( unsigned long ) pPublishInfo->payloadLength,
- ( unsigned long ) payloadLimit,
- MQTT_MAX_REMAINING_LENGTH ) );
- status = false;
- }
- else
- {
- /* Set the "Remaining length" output parameter and calculate the full
- * size of the PUBLISH packet. */
- *pRemainingLength = packetSize;
-
- packetSize += 1U + remainingLengthEncodedSize( packetSize );
- *pPacketSize = packetSize;
- }
- }
-
- LogDebug( ( "PUBLISH packet remaining length=%lu and packet size=%lu.",
- ( unsigned long ) *pRemainingLength,
- ( unsigned long ) *pPacketSize ) );
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializePublishHeaderWithoutTopic( const MQTTPublishInfo_t * pPublishInfo,
- size_t remainingLength,
- uint8_t * pBuffer,
- size_t * headerSize )
-{
- size_t headerLength;
- uint8_t * pIndex;
- MQTTStatus_t status = MQTTSuccess;
-
- /* The first byte of a PUBLISH packet contains the packet type and flags. */
- uint8_t publishFlags = MQTT_PACKET_TYPE_PUBLISH;
-
- /* Get the start address of the buffer. */
- pIndex = pBuffer;
-
- /* Length of serialized packet = First byte
- * + Length of encoded remaining length
- * + Encoded topic length. */
- headerLength = 1U + remainingLengthEncodedSize( remainingLength ) + 2U;
-
- if( pPublishInfo->qos == MQTTQoS1 )
- {
- LogDebug( ( "Adding QoS as QoS1 in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS1 );
- }
- else if( pPublishInfo->qos == MQTTQoS2 )
- {
- LogDebug( ( "Adding QoS as QoS2 in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS2 );
- }
- else
- {
- /* Empty else MISRA 15.7 */
- }
-
- if( pPublishInfo->retain == true )
- {
- LogDebug( ( "Adding retain bit in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_RETAIN );
- }
-
- if( pPublishInfo->dup == true )
- {
- LogDebug( ( "Adding dup bit in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_DUP );
- }
-
- *pIndex = publishFlags;
- pIndex++;
-
- /* The "Remaining length" is encoded from the second byte. */
- pIndex = encodeRemainingLength( pIndex, remainingLength );
-
- /* The first byte of a UTF-8 string is the high byte of the string length. */
- *pIndex = UINT16_HIGH_BYTE( pPublishInfo->topicNameLength );
- pIndex++;
-
- /* The second byte of a UTF-8 string is the low byte of the string length. */
- *pIndex = UINT16_LOW_BYTE( pPublishInfo->topicNameLength );
- pIndex++;
-
- *headerSize = headerLength;
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static void serializePublishCommon( const MQTTPublishInfo_t * pPublishInfo,
- size_t remainingLength,
- uint16_t packetIdentifier,
- const MQTTFixedBuffer_t * pFixedBuffer,
- bool serializePayload )
-{
- uint8_t * pIndex = NULL;
- const uint8_t * pPayloadBuffer = NULL;
-
- /* The first byte of a PUBLISH packet contains the packet type and flags. */
- uint8_t publishFlags = MQTT_PACKET_TYPE_PUBLISH;
-
- assert( pPublishInfo != NULL );
- assert( pFixedBuffer != NULL );
- assert( pFixedBuffer->pBuffer != NULL );
- /* Packet Id should be non zero for Qos 1 and Qos 2. */
- assert( ( pPublishInfo->qos == MQTTQoS0 ) || ( packetIdentifier != 0U ) );
- /* Duplicate flag should be set only for Qos 1 or Qos 2. */
- assert( ( pPublishInfo->dup != true ) || ( pPublishInfo->qos != MQTTQoS0 ) );
-
- /* Get the start address of the buffer. */
- pIndex = pFixedBuffer->pBuffer;
-
- if( pPublishInfo->qos == MQTTQoS1 )
- {
- LogDebug( ( "Adding QoS as QoS1 in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS1 );
- }
- else if( pPublishInfo->qos == MQTTQoS2 )
- {
- LogDebug( ( "Adding QoS as QoS2 in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS2 );
- }
- else
- {
- /* Empty else MISRA 15.7 */
- }
-
- if( pPublishInfo->retain == true )
- {
- LogDebug( ( "Adding retain bit in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_RETAIN );
- }
-
- if( pPublishInfo->dup == true )
- {
- LogDebug( ( "Adding dup bit in PUBLISH flags." ) );
- UINT8_SET_BIT( publishFlags, MQTT_PUBLISH_FLAG_DUP );
- }
-
- *pIndex = publishFlags;
- pIndex++;
-
- /* The "Remaining length" is encoded from the second byte. */
- pIndex = encodeRemainingLength( pIndex, remainingLength );
-
- /* The topic name is placed after the "Remaining length". */
- pIndex = encodeString( pIndex,
- pPublishInfo->pTopicName,
- pPublishInfo->topicNameLength );
-
- /* A packet identifier is required for QoS 1 and 2 messages. */
- if( pPublishInfo->qos > MQTTQoS0 )
- {
- LogDebug( ( "Adding packet Id in PUBLISH packet." ) );
- /* Place the packet identifier into the PUBLISH packet. */
- *pIndex = UINT16_HIGH_BYTE( packetIdentifier );
- pIndex[ 1U ] = UINT16_LOW_BYTE( packetIdentifier );
- pIndex = &pIndex[ 2U ];
- }
-
- /* The payload is placed after the packet identifier.
- * Payload is copied over only if required by the flag serializePayload.
- * This will help reduce an unnecessary copy of the payload into the buffer.
- */
- if( ( pPublishInfo->payloadLength > 0U ) &&
- ( serializePayload == true ) )
- {
- LogDebug( ( "Copying PUBLISH payload of length =%lu to buffer",
- ( unsigned long ) pPublishInfo->payloadLength ) );
-
- /* Typecast const void * typed payload buffer to const uint8_t *.
- * This is to use same type buffers in memcpy. */
- pPayloadBuffer = ( const uint8_t * ) pPublishInfo->pPayload;
-
- ( void ) memcpy( pIndex, pPayloadBuffer, pPublishInfo->payloadLength );
- /* Move the index to after the payload. */
- pIndex = &pIndex[ pPublishInfo->payloadLength ];
- }
-
- /* Ensure that the difference between the end and beginning of the buffer
- * is less than the buffer size. */
- assert( ( ( size_t ) ( pIndex - pFixedBuffer->pBuffer ) ) <= pFixedBuffer->size );
-}
-
-static size_t getRemainingLength( TransportRecv_t recvFunc,
- NetworkContext_t * pNetworkContext )
-{
- size_t remainingLength = 0, multiplier = 1, bytesDecoded = 0, expectedSize = 0;
- uint8_t encodedByte = 0;
- int32_t bytesReceived = 0;
-
- /* This algorithm is copied from the MQTT v3.1.1 spec. */
- do
- {
- if( multiplier > 2097152U ) /* 128 ^ 3 */
- {
- remainingLength = MQTT_REMAINING_LENGTH_INVALID;
- }
- else
- {
- bytesReceived = recvFunc( pNetworkContext, &encodedByte, 1U );
-
- if( bytesReceived == 1 )
- {
- remainingLength += ( ( size_t ) encodedByte & 0x7FU ) * multiplier;
- multiplier *= 128U;
- bytesDecoded++;
- }
- else
- {
- remainingLength = MQTT_REMAINING_LENGTH_INVALID;
- }
- }
-
- if( remainingLength == MQTT_REMAINING_LENGTH_INVALID )
- {
- break;
- }
- } while( ( encodedByte & 0x80U ) != 0U );
-
- /* Check that the decoded remaining length conforms to the MQTT specification. */
- if( remainingLength != MQTT_REMAINING_LENGTH_INVALID )
- {
- expectedSize = remainingLengthEncodedSize( remainingLength );
-
- if( bytesDecoded != expectedSize )
- {
- remainingLength = MQTT_REMAINING_LENGTH_INVALID;
- }
- }
-
- return remainingLength;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t processRemainingLength( const uint8_t * pBuffer,
- const size_t * pIndex,
- MQTTPacketInfo_t * pIncomingPacket )
-{
- size_t remainingLength = 0;
- size_t multiplier = 1;
- size_t bytesDecoded = 0;
- size_t expectedSize = 0;
- uint8_t encodedByte = 0;
- MQTTStatus_t status = MQTTSuccess;
-
- /* This algorithm is copied from the MQTT v3.1.1 spec. */
- do
- {
- if( multiplier > 2097152U ) /* 128 ^ 3 */
- {
- remainingLength = MQTT_REMAINING_LENGTH_INVALID;
-
- LogError( ( "Invalid remaining length in the packet.\n" ) );
-
- status = MQTTBadResponse;
- }
- else
- {
- if( *pIndex > ( bytesDecoded + 1U ) )
- {
- /* Get the next byte. It is at the next position after the bytes
- * decoded till now since the header of one byte was read before. */
- encodedByte = pBuffer[ bytesDecoded + 1U ];
-
- remainingLength += ( ( size_t ) encodedByte & 0x7FU ) * multiplier;
- multiplier *= 128U;
- bytesDecoded++;
- }
- else
- {
- status = MQTTNeedMoreBytes;
- }
- }
-
- /* If the response is incorrect, or no more data is available, then
- * break out of the loop. */
- if( ( remainingLength == MQTT_REMAINING_LENGTH_INVALID ) ||
- ( status != MQTTSuccess ) )
- {
- break;
- }
- } while( ( encodedByte & 0x80U ) != 0U );
-
- if( status == MQTTSuccess )
- {
- /* Check that the decoded remaining length conforms to the MQTT specification. */
- expectedSize = remainingLengthEncodedSize( remainingLength );
-
- if( bytesDecoded != expectedSize )
- {
- LogError( ( "Expected and actual length of decoded bytes do not match.\n" ) );
- status = MQTTBadResponse;
- }
- else
- {
- pIncomingPacket->remainingLength = remainingLength;
- pIncomingPacket->headerLength = bytesDecoded + 1U;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static bool incomingPacketValid( uint8_t packetType )
-{
- bool status = false;
-
- /* Check packet type. Mask out lower bits to ignore flags. */
- switch( packetType & 0xF0U )
- {
- /* Valid incoming packet types. */
- case MQTT_PACKET_TYPE_CONNACK:
- case MQTT_PACKET_TYPE_PUBLISH:
- case MQTT_PACKET_TYPE_PUBACK:
- case MQTT_PACKET_TYPE_PUBREC:
- case MQTT_PACKET_TYPE_PUBCOMP:
- case MQTT_PACKET_TYPE_SUBACK:
- case MQTT_PACKET_TYPE_UNSUBACK:
- case MQTT_PACKET_TYPE_PINGRESP:
- status = true;
- break;
-
- case ( MQTT_PACKET_TYPE_PUBREL & 0xF0U ):
-
- /* The second bit of a PUBREL must be set. */
- if( ( packetType & 0x02U ) > 0U )
- {
- status = true;
- }
-
- break;
-
- /* Any other packet type is invalid. */
- default:
- LogWarn( ( "Incoming packet invalid: Packet type=%u.",
- ( unsigned int ) packetType ) );
- break;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t checkPublishRemainingLength( size_t remainingLength,
- MQTTQoS_t qos,
- size_t qos0Minimum )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- /* Sanity checks for "Remaining length". */
- if( qos == MQTTQoS0 )
- {
- /* Check that the "Remaining length" is greater than the minimum. */
- if( remainingLength < qos0Minimum )
- {
- LogError( ( "QoS 0 PUBLISH cannot have a remaining length less than %lu.",
- ( unsigned long ) qos0Minimum ) );
-
- status = MQTTBadResponse;
- }
- }
- else
- {
- /* Check that the "Remaining length" is greater than the minimum. For
- * QoS 1 or 2, this will be two bytes greater than for QoS 0 due to the
- * packet identifier. */
- if( remainingLength < ( qos0Minimum + 2U ) )
- {
- LogError( ( "QoS 1 or 2 PUBLISH cannot have a remaining length less than %lu.",
- ( unsigned long ) ( qos0Minimum + 2U ) ) );
-
- status = MQTTBadResponse;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t processPublishFlags( uint8_t publishFlags,
- MQTTPublishInfo_t * pPublishInfo )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- assert( pPublishInfo != NULL );
-
- /* Check for QoS 2. */
- if( UINT8_CHECK_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS2 ) )
- {
- /* PUBLISH packet is invalid if both QoS 1 and QoS 2 bits are set. */
- if( UINT8_CHECK_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS1 ) )
- {
- LogError( ( "Bad QoS: 3." ) );
-
- status = MQTTBadResponse;
- }
- else
- {
- pPublishInfo->qos = MQTTQoS2;
- }
- }
- /* Check for QoS 1. */
- else if( UINT8_CHECK_BIT( publishFlags, MQTT_PUBLISH_FLAG_QOS1 ) )
- {
- pPublishInfo->qos = MQTTQoS1;
- }
- /* If the PUBLISH isn't QoS 1 or 2, then it's QoS 0. */
- else
- {
- pPublishInfo->qos = MQTTQoS0;
- }
-
- if( status == MQTTSuccess )
- {
- LogDebug( ( "QoS is %d.", ( int ) pPublishInfo->qos ) );
-
- /* Parse the Retain bit. */
- pPublishInfo->retain = UINT8_CHECK_BIT( publishFlags, MQTT_PUBLISH_FLAG_RETAIN );
-
- LogDebug( ( "Retain bit is %d.", ( int ) pPublishInfo->retain ) );
-
- /* Parse the DUP bit. */
- pPublishInfo->dup = UINT8_CHECK_BIT( publishFlags, MQTT_PUBLISH_FLAG_DUP );
-
- LogDebug( ( "DUP bit is %d.", ( int ) pPublishInfo->dup ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static void logConnackResponse( uint8_t responseCode )
-{
- const char * const pConnackResponses[ 6 ] =
- {
- "Connection accepted.", /* 0 */
- "Connection refused: unacceptable protocol version.", /* 1 */
- "Connection refused: identifier rejected.", /* 2 */
- "Connection refused: server unavailable", /* 3 */
- "Connection refused: bad user name or password.", /* 4 */
- "Connection refused: not authorized." /* 5 */
- };
-
- /* Avoid unused parameter warning when assert and logs are disabled. */
- ( void ) responseCode;
- ( void ) pConnackResponses;
-
- assert( responseCode <= 5U );
-
- if( responseCode == 0u )
- {
- /* Log at Debug level for a success CONNACK response. */
- LogDebug( ( "%s", pConnackResponses[ 0 ] ) );
- }
- else
- {
- /* Log an error based on the CONNACK response code. */
- LogError( ( "%s", pConnackResponses[ responseCode ] ) );
- }
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t deserializeConnack( const MQTTPacketInfo_t * pConnack,
- bool * pSessionPresent )
-{
- MQTTStatus_t status = MQTTSuccess;
- const uint8_t * pRemainingData = NULL;
-
- assert( pConnack != NULL );
- assert( pSessionPresent != NULL );
- pRemainingData = pConnack->pRemainingData;
-
- /* According to MQTT 3.1.1, the second byte of CONNACK must specify a
- * "Remaining length" of 2. */
- if( pConnack->remainingLength != MQTT_PACKET_CONNACK_REMAINING_LENGTH )
- {
- LogError( ( "CONNACK does not have remaining length of %u.",
- ( unsigned int ) MQTT_PACKET_CONNACK_REMAINING_LENGTH ) );
-
- status = MQTTBadResponse;
- }
-
- /* Check the reserved bits in CONNACK. The high 7 bits of the third byte
- * in CONNACK must be 0. */
- else if( ( pRemainingData[ 0 ] | 0x01U ) != 0x01U )
- {
- LogError( ( "Reserved bits in CONNACK incorrect." ) );
-
- status = MQTTBadResponse;
- }
- else
- {
- /* Determine if the "Session Present" bit is set. This is the lowest bit of
- * the third byte in CONNACK. */
- if( ( pRemainingData[ 0 ] & MQTT_PACKET_CONNACK_SESSION_PRESENT_MASK )
- == MQTT_PACKET_CONNACK_SESSION_PRESENT_MASK )
- {
- LogDebug( ( "CONNACK session present bit set." ) );
- *pSessionPresent = true;
-
- /* MQTT 3.1.1 specifies that the fourth byte in CONNACK must be 0 if the
- * "Session Present" bit is set. */
- if( pRemainingData[ 1 ] != 0U )
- {
- LogError( ( "Session Present bit is set, but connect return code in CONNACK is %u (nonzero).",
- ( unsigned int ) pRemainingData[ 1 ] ) );
- status = MQTTBadResponse;
- }
- }
- else
- {
- LogDebug( ( "CONNACK session present bit not set." ) );
- *pSessionPresent = false;
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* In MQTT 3.1.1, only values 0 through 5 are valid CONNACK response codes. */
- if( pRemainingData[ 1 ] > 5U )
- {
- LogError( ( "CONNACK response %u is invalid.",
- ( unsigned int ) pRemainingData[ 1 ] ) );
-
- status = MQTTBadResponse;
- }
- else
- {
- /* Print the appropriate message for the CONNACK response code if logs are
- * enabled. */
- logConnackResponse( pRemainingData[ 1 ] );
-
- /* A nonzero CONNACK response code means the connection was refused. */
- if( pRemainingData[ 1 ] > 0U )
- {
- status = MQTTServerRefused;
- }
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t calculateSubscriptionPacketSize( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- size_t * pRemainingLength,
- size_t * pPacketSize,
- MQTTSubscriptionType_t subscriptionType )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t i = 0, packetSize = 0;
-
- assert( pSubscriptionList != NULL );
- assert( subscriptionCount != 0U );
- assert( pRemainingLength != NULL );
- assert( pPacketSize != NULL );
-
- /* The variable header of a subscription packet consists of a 2-byte packet
- * identifier. */
- packetSize += sizeof( uint16_t );
-
- /* Sum the lengths of all subscription topic filters; add 1 byte for each
- * subscription's QoS if type is MQTT_SUBSCRIBE. */
- for( i = 0; i < subscriptionCount; i++ )
- {
- /* Add the length of the topic filter. MQTT strings are prepended
- * with 2 byte string length field. Hence 2 bytes are added to size. */
- packetSize += pSubscriptionList[ i ].topicFilterLength + sizeof( uint16_t );
-
- /* Only SUBSCRIBE packets include the QoS. */
- if( subscriptionType == MQTT_SUBSCRIBE )
- {
- packetSize += 1U;
- }
-
- /* Validate each topic filter. */
- if( ( pSubscriptionList[ i ].topicFilterLength == 0U ) ||
- ( pSubscriptionList[ i ].pTopicFilter == NULL ) )
- {
- status = MQTTBadParameter;
- LogError( ( "Subscription #%lu in %sSUBSCRIBE packet cannot be empty.",
- ( unsigned long ) i,
- ( subscriptionType == MQTT_SUBSCRIBE ) ? "" : "UN" ) );
- /* It is not necessary to break as an error status has already been set. */
- }
- }
-
- /* At this point, the "Remaining length" has been calculated. Return error
- * if the "Remaining length" exceeds what is allowed by MQTT 3.1.1. Otherwise,
- * set the output parameter.*/
- if( packetSize > MQTT_MAX_REMAINING_LENGTH )
- {
- LogError( ( "Subscription packet length of %lu exceeds"
- "the MQTT 3.1.1 maximum packet length of %lu.",
- ( unsigned long ) packetSize,
- MQTT_MAX_REMAINING_LENGTH ) );
- status = MQTTBadParameter;
- }
-
- if( status == MQTTSuccess )
- {
- *pRemainingLength = packetSize;
-
- /* Calculate the full size of the subscription packet by adding
- * number of bytes required to encode the "Remaining length" field
- * plus 1 byte for the "Packet type" field. */
- packetSize += 1U + remainingLengthEncodedSize( packetSize );
-
- /*Set the pPacketSize output parameter. */
- *pPacketSize = packetSize;
- }
-
- LogDebug( ( "Subscription packet remaining length=%lu and packet size=%lu.",
- ( unsigned long ) *pRemainingLength,
- ( unsigned long ) *pPacketSize ) );
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t readSubackStatus( size_t statusCount,
- const uint8_t * pStatusStart )
-{
- MQTTStatus_t status = MQTTSuccess;
- uint8_t subscriptionStatus = 0;
- size_t i = 0;
-
- assert( pStatusStart != NULL );
-
- /* Iterate through each status byte in the SUBACK packet. */
- for( i = 0; i < statusCount; i++ )
- {
- /* Read a single status byte in SUBACK. */
- subscriptionStatus = pStatusStart[ i ];
-
- /* MQTT 3.1.1 defines the following values as status codes. */
- switch( subscriptionStatus )
- {
- case 0x00:
- case 0x01:
- case 0x02:
-
- LogDebug( ( "Topic filter %lu accepted, max QoS %u.",
- ( unsigned long ) i,
- ( unsigned int ) subscriptionStatus ) );
- break;
-
- case 0x80:
-
- LogWarn( ( "Topic filter %lu refused.", ( unsigned long ) i ) );
-
- /* Application should remove subscription from the list */
- status = MQTTServerRefused;
-
- break;
-
- default:
- LogError( ( "Bad SUBSCRIBE status %u.",
- ( unsigned int ) subscriptionStatus ) );
-
- status = MQTTBadResponse;
-
- break;
- }
-
- /* Stop parsing the subscription statuses if a bad response was received. */
- if( status == MQTTBadResponse )
- {
- break;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t deserializeSuback( const MQTTPacketInfo_t * pSuback,
- uint16_t * pPacketIdentifier )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t remainingLength;
- const uint8_t * pVariableHeader = NULL;
-
- assert( pSuback != NULL );
- assert( pPacketIdentifier != NULL );
-
- remainingLength = pSuback->remainingLength;
- pVariableHeader = pSuback->pRemainingData;
-
- /* A SUBACK must have a remaining length of at least 3 to accommodate the
- * packet identifier and at least 1 return code. */
- if( remainingLength < 3U )
- {
- LogError( ( "SUBACK cannot have a remaining length less than 3." ) );
- status = MQTTBadResponse;
- }
- else
- {
- /* Extract the packet identifier (first 2 bytes of variable header) from SUBACK. */
- *pPacketIdentifier = UINT16_DECODE( pVariableHeader );
-
- LogDebug( ( "Packet identifier %hu.",
- ( unsigned short ) *pPacketIdentifier ) );
-
- if( *pPacketIdentifier == 0U )
- {
- status = MQTTBadResponse;
- }
- else
- {
- status = readSubackStatus( remainingLength - sizeof( uint16_t ),
- &pVariableHeader[ sizeof( uint16_t ) ] );
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t validateSubscriptionSerializeParams( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t packetSize = 0;
-
- /* Validate all the parameters. */
- if( ( pFixedBuffer == NULL ) || ( pSubscriptionList == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer=%p, "
- "pSubscriptionList=%p.",
- ( void * ) pFixedBuffer,
- ( void * ) pSubscriptionList ) );
- status = MQTTBadParameter;
- }
- /* A buffer must be configured for serialization. */
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer->pBuffer is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( subscriptionCount == 0U )
- {
- LogError( ( "Subscription count is 0." ) );
- status = MQTTBadParameter;
- }
- else if( packetId == 0U )
- {
- LogError( ( "Packet Id for subscription packet is 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* The serialized packet size = First byte
- * + length of encoded size of remaining length
- * + remaining length. */
- packetSize = 1U + remainingLengthEncodedSize( remainingLength )
- + remainingLength;
-
- if( packetSize > pFixedBuffer->size )
- {
- LogError( ( "Buffer size of %lu is not sufficient to hold "
- "serialized packet of size of %lu.",
- ( unsigned long ) pFixedBuffer->size,
- ( unsigned long ) packetSize ) );
- status = MQTTNoMemory;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t deserializePublish( const MQTTPacketInfo_t * pIncomingPacket,
- uint16_t * pPacketId,
- MQTTPublishInfo_t * pPublishInfo )
-{
- MQTTStatus_t status = MQTTSuccess;
- const uint8_t * pVariableHeader, * pPacketIdentifierHigh = NULL;
-
- assert( pIncomingPacket != NULL );
- assert( pPacketId != NULL );
- assert( pPublishInfo != NULL );
- assert( pIncomingPacket->pRemainingData != NULL );
-
- pVariableHeader = pIncomingPacket->pRemainingData;
- /* The flags are the lower 4 bits of the first byte in PUBLISH. */
- status = processPublishFlags( ( pIncomingPacket->type & 0x0FU ), pPublishInfo );
-
- if( status == MQTTSuccess )
- {
- /* Sanity checks for "Remaining length". A QoS 0 PUBLISH must have a remaining
- * length of at least 3 to accommodate topic name length (2 bytes) and topic
- * name (at least 1 byte). A QoS 1 or 2 PUBLISH must have a remaining length of
- * at least 5 for the packet identifier in addition to the topic name length and
- * topic name. */
- status = checkPublishRemainingLength( pIncomingPacket->remainingLength,
- pPublishInfo->qos,
- MQTT_MIN_PUBLISH_REMAINING_LENGTH_QOS0 );
- }
-
- if( status == MQTTSuccess )
- {
- /* Extract the topic name starting from the first byte of the variable header.
- * The topic name string starts at byte 3 in the variable header. */
- pPublishInfo->topicNameLength = UINT16_DECODE( pVariableHeader );
-
- /* Sanity checks for topic name length and "Remaining length". The remaining
- * length must be at least as large as the variable length header. */
- status = checkPublishRemainingLength( pIncomingPacket->remainingLength,
- pPublishInfo->qos,
- pPublishInfo->topicNameLength + sizeof( uint16_t ) );
- }
-
- if( status == MQTTSuccess )
- {
- /* Parse the topic. */
- pPublishInfo->pTopicName = ( const char * ) ( &pVariableHeader[ sizeof( uint16_t ) ] );
- LogDebug( ( "Topic name length: %hu.", ( unsigned short ) pPublishInfo->topicNameLength ) );
-
- /* Extract the packet identifier for QoS 1 or 2 PUBLISH packets. Packet
- * identifier starts immediately after the topic name. */
- pPacketIdentifierHigh = ( const uint8_t * ) ( &pPublishInfo->pTopicName[ pPublishInfo->topicNameLength ] );
-
- if( pPublishInfo->qos > MQTTQoS0 )
- {
- *pPacketId = UINT16_DECODE( pPacketIdentifierHigh );
-
- LogDebug( ( "Packet identifier %hu.",
- ( unsigned short ) *pPacketId ) );
-
- /* Advance pointer two bytes to start of payload as in the QoS 0 case. */
- pPacketIdentifierHigh = &pPacketIdentifierHigh[ sizeof( uint16_t ) ];
-
- /* Packet identifier cannot be 0. */
- if( *pPacketId == 0U )
- {
- LogError( ( "Packet identifier cannot be 0." ) );
- status = MQTTBadResponse;
- }
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Calculate the length of the payload. QoS 1 or 2 PUBLISH packets contain
- * a packet identifier, but QoS 0 PUBLISH packets do not. */
- pPublishInfo->payloadLength = pIncomingPacket->remainingLength - pPublishInfo->topicNameLength - sizeof( uint16_t );
-
- if( pPublishInfo->qos != MQTTQoS0 )
- {
- /* Two more bytes for the packet identifier. */
- pPublishInfo->payloadLength -= sizeof( uint16_t );
- }
-
- /* Set payload if it exists. */
- pPublishInfo->pPayload = ( pPublishInfo->payloadLength != 0U ) ? pPacketIdentifierHigh : NULL;
-
- LogDebug( ( "Payload length %lu.",
- ( unsigned long ) pPublishInfo->payloadLength ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t deserializeSimpleAck( const MQTTPacketInfo_t * pAck,
- uint16_t * pPacketIdentifier )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- assert( pAck != NULL );
- assert( pPacketIdentifier != NULL );
-
- /* Check that the "Remaining length" of the received ACK is 2. */
- if( pAck->remainingLength != MQTT_PACKET_SIMPLE_ACK_REMAINING_LENGTH )
- {
- LogError( ( "ACK does not have remaining length of %u.",
- ( unsigned int ) MQTT_PACKET_SIMPLE_ACK_REMAINING_LENGTH ) );
-
- status = MQTTBadResponse;
- }
- else
- {
- /* Extract the packet identifier (third and fourth bytes) from ACK. */
- *pPacketIdentifier = UINT16_DECODE( pAck->pRemainingData );
-
- LogDebug( ( "Packet identifier %hu.",
- ( unsigned short ) *pPacketIdentifier ) );
-
- /* Packet identifier cannot be 0. */
- if( *pPacketIdentifier == 0U )
- {
- LogError( ( "Packet identifier cannot be 0." ) );
- status = MQTTBadResponse;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t deserializePingresp( const MQTTPacketInfo_t * pPingresp )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- assert( pPingresp != NULL );
-
- /* Check the "Remaining length" (second byte) of the received PINGRESP is 0. */
- if( pPingresp->remainingLength != MQTT_PACKET_PINGRESP_REMAINING_LENGTH )
- {
- LogError( ( "PINGRESP does not have remaining length of %u.",
- MQTT_PACKET_PINGRESP_REMAINING_LENGTH ) );
-
- status = MQTTBadResponse;
- }
-
- return status;
-}
-
-uint8_t * MQTT_SerializeConnectFixedHeader( uint8_t * pIndex,
- const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength )
-{
- uint8_t * pIndexLocal = pIndex;
- uint8_t connectFlags = 0U;
-
- /* The first byte in the CONNECT packet is the control packet type. */
- *pIndexLocal = MQTT_PACKET_TYPE_CONNECT;
- pIndexLocal++;
-
- /* The remaining length of the CONNECT packet is encoded starting from the
- * second byte. The remaining length does not include the length of the fixed
- * header or the encoding of the remaining length. */
- pIndexLocal = encodeRemainingLength( pIndexLocal, remainingLength );
-
- /* The string "MQTT" is placed at the beginning of the CONNECT packet's variable
- * header. This string is 4 bytes long. */
- pIndexLocal = encodeString( pIndexLocal, "MQTT", 4 );
-
- /* The MQTT protocol version is the second field of the variable header. */
- *pIndexLocal = MQTT_VERSION_3_1_1;
- pIndexLocal++;
-
- /* Set the clean session flag if needed. */
- if( pConnectInfo->cleanSession == true )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_CLEAN );
- }
-
- /* Set the flags for username and password if provided. */
- if( pConnectInfo->pUserName != NULL )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_USERNAME );
- }
-
- if( pConnectInfo->pPassword != NULL )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_PASSWORD );
- }
-
- /* Set will flag if a Last Will and Testament is provided. */
- if( pWillInfo != NULL )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_WILL );
-
- /* Flags only need to be changed for Will QoS 1 or 2. */
- if( pWillInfo->qos == MQTTQoS1 )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_WILL_QOS1 );
- }
- else if( pWillInfo->qos == MQTTQoS2 )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_WILL_QOS2 );
- }
- else
- {
- /* Empty else MISRA 15.7 */
- }
-
- if( pWillInfo->retain == true )
- {
- UINT8_SET_BIT( connectFlags, MQTT_CONNECT_FLAG_WILL_RETAIN );
- }
- }
-
- *pIndexLocal = connectFlags;
- pIndexLocal++;
-
- /* Write the 2 bytes of the keep alive interval into the CONNECT packet. */
- pIndexLocal[ 0 ] = UINT16_HIGH_BYTE( pConnectInfo->keepAliveSeconds );
- pIndexLocal[ 1 ] = UINT16_LOW_BYTE( pConnectInfo->keepAliveSeconds );
- pIndexLocal = &pIndexLocal[ 2 ];
-
- return pIndexLocal;
-}
-/*-----------------------------------------------------------*/
-
-static void serializeConnectPacket( const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer )
-{
- uint8_t * pIndex = NULL;
-
- assert( pConnectInfo != NULL );
- assert( pFixedBuffer != NULL );
- assert( pFixedBuffer->pBuffer != NULL );
-
- pIndex = pFixedBuffer->pBuffer;
-
- /* Serialize the header. */
- pIndex = MQTT_SerializeConnectFixedHeader( pIndex,
- pConnectInfo,
- pWillInfo,
- remainingLength );
-
- /* Write the client identifier into the CONNECT packet. */
- pIndex = encodeString( pIndex,
- pConnectInfo->pClientIdentifier,
- pConnectInfo->clientIdentifierLength );
-
- /* Write the will topic name and message into the CONNECT packet if provided. */
- if( pWillInfo != NULL )
- {
- pIndex = encodeString( pIndex,
- pWillInfo->pTopicName,
- pWillInfo->topicNameLength );
-
- pIndex = encodeString( pIndex,
- pWillInfo->pPayload,
- ( uint16_t ) pWillInfo->payloadLength );
- }
-
- /* Encode the user name if provided. */
- if( pConnectInfo->pUserName != NULL )
- {
- pIndex = encodeString( pIndex, pConnectInfo->pUserName, pConnectInfo->userNameLength );
- }
-
- /* Encode the password if provided. */
- if( pConnectInfo->pPassword != NULL )
- {
- pIndex = encodeString( pIndex, pConnectInfo->pPassword, pConnectInfo->passwordLength );
- }
-
- LogDebug( ( "Length of serialized CONNECT packet is %lu.",
- ( ( unsigned long ) ( pIndex - pFixedBuffer->pBuffer ) ) ) );
-
- /* Ensure that the difference between the end and beginning of the buffer
- * is less than the buffer size. */
- assert( ( ( size_t ) ( pIndex - pFixedBuffer->pBuffer ) ) <= pFixedBuffer->size );
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetConnectPacketSize( const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t * pRemainingLength,
- size_t * pPacketSize )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t remainingLength;
-
- /* The CONNECT packet will always include a 10-byte variable header. */
- size_t connectPacketSize = MQTT_PACKET_CONNECT_HEADER_SIZE;
-
- /* Validate arguments. */
- if( ( pConnectInfo == NULL ) || ( pRemainingLength == NULL ) ||
- ( pPacketSize == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pConnectInfo=%p, "
- "pRemainingLength=%p, pPacketSize=%p.",
- ( void * ) pConnectInfo,
- ( void * ) pRemainingLength,
- ( void * ) pPacketSize ) );
- status = MQTTBadParameter;
- }
- else if( ( pConnectInfo->clientIdentifierLength == 0U ) || ( pConnectInfo->pClientIdentifier == NULL ) )
- {
- LogError( ( "Mqtt_GetConnectPacketSize() client identifier must be set." ) );
- status = MQTTBadParameter;
- }
- else if( ( pWillInfo != NULL ) && ( pWillInfo->payloadLength > ( size_t ) UINT16_MAX ) )
- {
- /* The MQTTPublishInfo_t is reused for the will message. The payload
- * length for any other message could be larger than 65,535, but
- * the will message length is required to be represented in 2 bytes.
- * By bounding the payloadLength of the will message, the CONNECT
- * packet will never be larger than 327699 bytes. */
- LogError( ( "The Will Message length must not exceed %d. "
- "pWillInfo->payloadLength=%lu.",
- UINT16_MAX,
- ( unsigned long ) pWillInfo->payloadLength ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Add the length of the client identifier. */
- connectPacketSize += pConnectInfo->clientIdentifierLength + sizeof( uint16_t );
-
- /* Add the lengths of the will message and topic name if provided. */
- if( pWillInfo != NULL )
- {
- connectPacketSize += pWillInfo->topicNameLength + sizeof( uint16_t ) +
- pWillInfo->payloadLength + sizeof( uint16_t );
- }
-
- /* Add the lengths of the user name and password if provided. */
- if( pConnectInfo->pUserName != NULL )
- {
- connectPacketSize += pConnectInfo->userNameLength + sizeof( uint16_t );
- }
-
- if( pConnectInfo->pPassword != NULL )
- {
- connectPacketSize += pConnectInfo->passwordLength + sizeof( uint16_t );
- }
-
- /* At this point, the "Remaining Length" field of the MQTT CONNECT packet has
- * been calculated. */
- remainingLength = connectPacketSize;
-
- /* Calculate the full size of the MQTT CONNECT packet by adding the size of
- * the "Remaining Length" field plus 1 byte for the "Packet Type" field. */
- connectPacketSize += 1U + remainingLengthEncodedSize( connectPacketSize );
-
- /* The connectPacketSize calculated from this function's parameters is
- * guaranteed to be less than the maximum MQTT CONNECT packet size, which
- * is 327700. If the maximum client identifier length, the maximum will
- * message topic length, the maximum will topic payload length, the
- * maximum username length, and the maximum password length are all present
- * in the MQTT CONNECT packet, the total size will be calculated to be
- * 327699:
- * (variable length header)10 +
- * (maximum client identifier length) 65535 + (encoded length) 2 +
- * (maximum will message topic name length) 65535 + (encoded length)2 +
- * (maximum will message payload length) 65535 + 2 +
- * (maximum username length) 65535 + (encoded length) 2 +
- * (maximum password length) 65535 + (encoded length) 2 +
- * (packet type field length) 1 +
- * (CONNECT packet encoded length) 3 = 327699 */
-
- *pRemainingLength = remainingLength;
- *pPacketSize = connectPacketSize;
-
- LogDebug( ( "CONNECT packet remaining length=%lu and packet size=%lu.",
- ( unsigned long ) *pRemainingLength,
- ( unsigned long ) *pPacketSize ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializeConnect( const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t connectPacketSize = 0;
-
- /* Validate arguments. */
- if( ( pConnectInfo == NULL ) || ( pFixedBuffer == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pConnectInfo=%p, "
- "pFixedBuffer=%p.",
- ( void * ) pConnectInfo,
- ( void * ) pFixedBuffer ) );
- status = MQTTBadParameter;
- }
- /* A buffer must be configured for serialization. */
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer->pBuffer is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( ( pWillInfo != NULL ) && ( pWillInfo->pTopicName == NULL ) )
- {
- LogError( ( "pWillInfo->pTopicName cannot be NULL if Will is present." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Calculate CONNECT packet size. Overflow in in this addition is not checked
- * because it is part of the API contract to call Mqtt_GetConnectPacketSize()
- * before this function. */
- connectPacketSize = remainingLength + remainingLengthEncodedSize( remainingLength ) + 1U;
-
- /* Check that the full packet size fits within the given buffer. */
- if( connectPacketSize > pFixedBuffer->size )
- {
- LogError( ( "Buffer size of %lu is not sufficient to hold "
- "serialized CONNECT packet of size of %lu.",
- ( unsigned long ) pFixedBuffer->size,
- ( unsigned long ) connectPacketSize ) );
- status = MQTTNoMemory;
- }
- else
- {
- serializeConnectPacket( pConnectInfo,
- pWillInfo,
- remainingLength,
- pFixedBuffer );
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetSubscribePacketSize( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- size_t * pRemainingLength,
- size_t * pPacketSize )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- /* Validate parameters. */
- if( ( pSubscriptionList == NULL ) || ( pRemainingLength == NULL ) ||
- ( pPacketSize == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pSubscriptionList=%p, "
- "pRemainingLength=%p, pPacketSize=%p.",
- ( void * ) pSubscriptionList,
- ( void * ) pRemainingLength,
- ( void * ) pPacketSize ) );
- status = MQTTBadParameter;
- }
- else if( subscriptionCount == 0U )
- {
- LogError( ( "subscriptionCount is 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Calculate the MQTT SUBSCRIBE packet size. */
- status = calculateSubscriptionPacketSize( pSubscriptionList,
- subscriptionCount,
- pRemainingLength,
- pPacketSize,
- MQTT_SUBSCRIBE );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-uint8_t * MQTT_SerializeSubscribeHeader( size_t remainingLength,
- uint8_t * pIndex,
- uint16_t packetId )
-{
- uint8_t * pIterator = pIndex;
-
- /* The first byte in SUBSCRIBE is the packet type. */
- *pIterator = MQTT_PACKET_TYPE_SUBSCRIBE;
- pIterator++;
-
- /* Encode the "Remaining length" starting from the second byte. */
- pIterator = encodeRemainingLength( pIterator, remainingLength );
-
- /* Place the packet identifier into the SUBSCRIBE packet. */
- pIterator[ 0 ] = UINT16_HIGH_BYTE( packetId );
- pIterator[ 1 ] = UINT16_LOW_BYTE( packetId );
- /* Advance the pointer. */
- pIterator = &pIterator[ 2 ];
-
- return pIterator;
-}
-
-/*-----------------------------------------------------------*/
-
-uint8_t * MQTT_SerializeUnsubscribeHeader( size_t remainingLength,
- uint8_t * pIndex,
- uint16_t packetId )
-{
- uint8_t * pIterator = pIndex;
-
- /* The first byte in UNSUBSCRIBE is the packet type. */
- *pIterator = MQTT_PACKET_TYPE_UNSUBSCRIBE;
- pIterator++;
-
- /* Encode the "Remaining length" starting from the second byte. */
- pIterator = encodeRemainingLength( pIterator, remainingLength );
-
- /* Place the packet identifier into the SUBSCRIBE packet. */
- pIterator[ 0 ] = UINT16_HIGH_BYTE( packetId );
- pIterator[ 1 ] = UINT16_LOW_BYTE( packetId );
- /* Increment the pointer. */
- pIterator = &pIterator[ 2 ];
-
- return pIterator;
-}
-
-MQTTStatus_t MQTT_SerializeSubscribe( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer )
-{
- size_t i = 0;
- uint8_t * pIndex = NULL;
-
- /* Validate all the parameters. */
- MQTTStatus_t status =
- validateSubscriptionSerializeParams( pSubscriptionList,
- subscriptionCount,
- packetId,
- remainingLength,
- pFixedBuffer );
-
- if( status == MQTTSuccess )
- {
- pIndex = pFixedBuffer->pBuffer;
-
- pIndex = MQTT_SerializeSubscribeHeader( remainingLength,
- pIndex,
- packetId );
-
- /* Serialize each subscription topic filter and QoS. */
- for( i = 0; i < subscriptionCount; i++ )
- {
- pIndex = encodeString( pIndex,
- pSubscriptionList[ i ].pTopicFilter,
- pSubscriptionList[ i ].topicFilterLength );
-
- /* Place the QoS in the SUBSCRIBE packet. */
- *pIndex = ( uint8_t ) ( pSubscriptionList[ i ].qos );
- pIndex++;
- }
-
- LogDebug( ( "Length of serialized SUBSCRIBE packet is %lu.",
- ( ( unsigned long ) ( pIndex - pFixedBuffer->pBuffer ) ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetUnsubscribePacketSize( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- size_t * pRemainingLength,
- size_t * pPacketSize )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- /* Validate parameters. */
- if( ( pSubscriptionList == NULL ) || ( pRemainingLength == NULL ) ||
- ( pPacketSize == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pSubscriptionList=%p, "
- "pRemainingLength=%p, pPacketSize=%p.",
- ( void * ) pSubscriptionList,
- ( void * ) pRemainingLength,
- ( void * ) pPacketSize ) );
- status = MQTTBadParameter;
- }
- else if( subscriptionCount == 0U )
- {
- LogError( ( "Subscription count is 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Calculate the MQTT UNSUBSCRIBE packet size. */
- status = calculateSubscriptionPacketSize( pSubscriptionList,
- subscriptionCount,
- pRemainingLength,
- pPacketSize,
- MQTT_UNSUBSCRIBE );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializeUnsubscribe( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t i = 0;
- uint8_t * pIndex = NULL;
-
- /* Validate all the parameters. */
- status = validateSubscriptionSerializeParams( pSubscriptionList,
- subscriptionCount,
- packetId,
- remainingLength,
- pFixedBuffer );
-
- if( status == MQTTSuccess )
- {
- /* Get the start of the buffer to the iterator variable. */
- pIndex = pFixedBuffer->pBuffer;
-
- pIndex = MQTT_SerializeUnsubscribeHeader( remainingLength, pIndex, packetId );
-
- /* Serialize each subscription topic filter. */
- for( i = 0; i < subscriptionCount; i++ )
- {
- pIndex = encodeString( pIndex,
- pSubscriptionList[ i ].pTopicFilter,
- pSubscriptionList[ i ].topicFilterLength );
- }
-
- LogDebug( ( "Length of serialized UNSUBSCRIBE packet is %lu.",
- ( ( unsigned long ) ( pIndex - pFixedBuffer->pBuffer ) ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetPublishPacketSize( const MQTTPublishInfo_t * pPublishInfo,
- size_t * pRemainingLength,
- size_t * pPacketSize )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( ( pPublishInfo == NULL ) || ( pRemainingLength == NULL ) || ( pPacketSize == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pPublishInfo=%p, "
- "pRemainingLength=%p, pPacketSize=%p.",
- ( void * ) pPublishInfo,
- ( void * ) pRemainingLength,
- ( void * ) pPacketSize ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->pTopicName == NULL ) || ( pPublishInfo->topicNameLength == 0U ) )
- {
- LogError( ( "Invalid topic name for PUBLISH: pTopicName=%p, "
- "topicNameLength=%hu.",
- ( void * ) pPublishInfo->pTopicName,
- ( unsigned short ) pPublishInfo->topicNameLength ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Calculate the "Remaining length" field and total packet size. If it exceeds
- * what is allowed in the MQTT standard, return an error. */
- if( calculatePublishPacketSize( pPublishInfo, pRemainingLength, pPacketSize ) == false )
- {
- LogError( ( "PUBLISH packet remaining length exceeds %lu, which is the "
- "maximum size allowed by MQTT 3.1.1.",
- MQTT_MAX_REMAINING_LENGTH ) );
- status = MQTTBadParameter;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializePublish( const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t packetSize = 0;
-
- if( ( pFixedBuffer == NULL ) || ( pPublishInfo == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer=%p, "
- "pPublishInfo=%p.",
- ( void * ) pFixedBuffer,
- ( void * ) pPublishInfo ) );
- status = MQTTBadParameter;
- }
- /* A buffer must be configured for serialization. */
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer->pBuffer is NULL." ) );
- status = MQTTBadParameter;
- }
-
- /* For serializing a publish, if there exists a payload, then the buffer
- * cannot be NULL. */
- else if( ( pPublishInfo->payloadLength > 0U ) && ( pPublishInfo->pPayload == NULL ) )
- {
- LogError( ( "A nonzero payload length requires a non-NULL payload: "
- "payloadLength=%lu, pPayload=%p.",
- ( unsigned long ) pPublishInfo->payloadLength,
- pPublishInfo->pPayload ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->pTopicName == NULL ) || ( pPublishInfo->topicNameLength == 0U ) )
- {
- LogError( ( "Invalid topic name for PUBLISH: pTopicName=%p, "
- "topicNameLength=%hu.",
- ( void * ) pPublishInfo->pTopicName,
- ( unsigned short ) pPublishInfo->topicNameLength ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->qos != MQTTQoS0 ) && ( packetId == 0U ) )
- {
- LogError( ( "Packet ID is 0 for PUBLISH with QoS=%u.",
- ( unsigned int ) pPublishInfo->qos ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->dup == true ) && ( pPublishInfo->qos == MQTTQoS0 ) )
- {
- LogError( ( "Duplicate flag is set for PUBLISH with Qos 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Length of serialized packet = First byte
- * + Length of encoded remaining length
- * + Remaining length. */
- packetSize = 1U + remainingLengthEncodedSize( remainingLength )
- + remainingLength;
- }
-
- if( ( status == MQTTSuccess ) && ( packetSize > pFixedBuffer->size ) )
- {
- LogError( ( "Buffer size of %lu is not sufficient to hold "
- "serialized PUBLISH packet of size of %lu.",
- ( unsigned long ) pFixedBuffer->size,
- ( unsigned long ) packetSize ) );
- status = MQTTNoMemory;
- }
-
- if( status == MQTTSuccess )
- {
- /* Serialize publish with header and payload. */
- serializePublishCommon( pPublishInfo,
- remainingLength,
- packetId,
- pFixedBuffer,
- true );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializePublishHeader( const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer,
- size_t * pHeaderSize )
-{
- MQTTStatus_t status = MQTTSuccess;
- size_t packetSize = 0;
-
- if( ( pFixedBuffer == NULL ) || ( pPublishInfo == NULL ) ||
- ( pHeaderSize == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer=%p, "
- "pPublishInfo=%p, pHeaderSize=%p.",
- ( void * ) pFixedBuffer,
- ( void * ) pPublishInfo,
- ( void * ) pHeaderSize ) );
- status = MQTTBadParameter;
- }
- /* A buffer must be configured for serialization. */
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "Argument cannot be NULL: pFixedBuffer->pBuffer is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->pTopicName == NULL ) || ( pPublishInfo->topicNameLength == 0U ) )
- {
- LogError( ( "Invalid topic name for publish: pTopicName=%p, "
- "topicNameLength=%hu.",
- ( void * ) pPublishInfo->pTopicName,
- ( unsigned short ) pPublishInfo->topicNameLength ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->qos != MQTTQoS0 ) && ( packetId == 0U ) )
- {
- LogError( ( "Packet Id is 0 for publish with QoS=%hu.",
- ( unsigned short ) pPublishInfo->qos ) );
- status = MQTTBadParameter;
- }
- else if( ( pPublishInfo->dup == true ) && ( pPublishInfo->qos == MQTTQoS0 ) )
- {
- LogError( ( "Duplicate flag is set for PUBLISH with Qos 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Length of serialized packet = First byte
- * + Length of encoded remaining length
- * + Remaining length
- * - Payload Length.
- */
- packetSize = 1U + remainingLengthEncodedSize( remainingLength )
- + remainingLength
- - pPublishInfo->payloadLength;
- }
-
- if( ( status == MQTTSuccess ) && ( packetSize > pFixedBuffer->size ) )
- {
- LogError( ( "Buffer size of %lu is not sufficient to hold "
- "serialized PUBLISH header packet of size of %lu.",
- ( unsigned long ) pFixedBuffer->size,
- ( unsigned long ) ( packetSize - pPublishInfo->payloadLength ) ) );
- status = MQTTNoMemory;
- }
-
- if( status == MQTTSuccess )
- {
- /* Serialize publish without copying the payload. */
- serializePublishCommon( pPublishInfo,
- remainingLength,
- packetId,
- pFixedBuffer,
- false );
-
- /* Header size is the same as calculated packet size. */
- *pHeaderSize = packetSize;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializeAck( const MQTTFixedBuffer_t * pFixedBuffer,
- uint8_t packetType,
- uint16_t packetId )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pFixedBuffer == NULL )
- {
- LogError( ( "Provided buffer is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "pFixedBuffer->pBuffer cannot be NULL." ) );
- status = MQTTBadParameter;
- }
- /* The buffer must be able to fit 4 bytes for the packet. */
- else if( pFixedBuffer->size < MQTT_PUBLISH_ACK_PACKET_SIZE )
- {
- LogError( ( "Insufficient memory for packet." ) );
- status = MQTTNoMemory;
- }
- else if( packetId == 0U )
- {
- LogError( ( "Packet ID cannot be 0." ) );
- status = MQTTBadParameter;
- }
- else
- {
- switch( packetType )
- {
- /* Only publish acks are serialized by the client. */
- case MQTT_PACKET_TYPE_PUBACK:
- case MQTT_PACKET_TYPE_PUBREC:
- case MQTT_PACKET_TYPE_PUBREL:
- case MQTT_PACKET_TYPE_PUBCOMP:
- pFixedBuffer->pBuffer[ 0 ] = packetType;
- pFixedBuffer->pBuffer[ 1 ] = MQTT_PACKET_SIMPLE_ACK_REMAINING_LENGTH;
- pFixedBuffer->pBuffer[ 2 ] = UINT16_HIGH_BYTE( packetId );
- pFixedBuffer->pBuffer[ 3 ] = UINT16_LOW_BYTE( packetId );
- break;
-
- default:
- LogError( ( "Packet type is not a publish ACK: Packet type=%02x",
- ( unsigned int ) packetType ) );
- status = MQTTBadParameter;
- break;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetDisconnectPacketSize( size_t * pPacketSize )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pPacketSize == NULL )
- {
- LogError( ( "pPacketSize is NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* MQTT DISCONNECT packets always have the same size. */
- *pPacketSize = MQTT_DISCONNECT_PACKET_SIZE;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializeDisconnect( const MQTTFixedBuffer_t * pFixedBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- /* Validate arguments. */
- if( pFixedBuffer == NULL )
- {
- LogError( ( "pFixedBuffer cannot be NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "pFixedBuffer->pBuffer cannot be NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Empty else MISRA 15.7 */
- }
-
- if( status == MQTTSuccess )
- {
- if( pFixedBuffer->size < MQTT_DISCONNECT_PACKET_SIZE )
- {
- LogError( ( "Buffer size of %lu is not sufficient to hold "
- "serialized DISCONNECT packet of size of %lu.",
- ( unsigned long ) pFixedBuffer->size,
- MQTT_DISCONNECT_PACKET_SIZE ) );
- status = MQTTNoMemory;
- }
- }
-
- if( status == MQTTSuccess )
- {
- pFixedBuffer->pBuffer[ 0 ] = MQTT_PACKET_TYPE_DISCONNECT;
- pFixedBuffer->pBuffer[ 1 ] = MQTT_DISCONNECT_REMAINING_LENGTH;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetPingreqPacketSize( size_t * pPacketSize )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pPacketSize == NULL )
- {
- LogError( ( "pPacketSize is NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* MQTT PINGREQ packets always have the same size. */
- *pPacketSize = MQTT_PACKET_PINGREQ_SIZE;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_SerializePingreq( const MQTTFixedBuffer_t * pFixedBuffer )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pFixedBuffer == NULL )
- {
- LogError( ( "pFixedBuffer is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pFixedBuffer->pBuffer == NULL )
- {
- LogError( ( "pFixedBuffer->pBuffer cannot be NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Empty else MISRA 15.7 */
- }
-
- if( status == MQTTSuccess )
- {
- if( pFixedBuffer->size < MQTT_PACKET_PINGREQ_SIZE )
- {
- LogError( ( "Buffer size of %lu is not sufficient to hold "
- "serialized PINGREQ packet of size of %lu.",
- ( unsigned long ) pFixedBuffer->size,
- MQTT_PACKET_PINGREQ_SIZE ) );
- status = MQTTNoMemory;
- }
- }
-
- if( status == MQTTSuccess )
- {
- /* Ping request packets are always the same. */
- pFixedBuffer->pBuffer[ 0 ] = MQTT_PACKET_TYPE_PINGREQ;
- pFixedBuffer->pBuffer[ 1 ] = 0x00;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_DeserializePublish( const MQTTPacketInfo_t * pIncomingPacket,
- uint16_t * pPacketId,
- MQTTPublishInfo_t * pPublishInfo )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( ( pIncomingPacket == NULL ) || ( pPacketId == NULL ) || ( pPublishInfo == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pIncomingPacket=%p, "
- "pPacketId=%p, pPublishInfo=%p",
- ( void * ) pIncomingPacket,
- ( void * ) pPacketId,
- ( void * ) pPublishInfo ) );
- status = MQTTBadParameter;
- }
- else if( ( pIncomingPacket->type & 0xF0U ) != MQTT_PACKET_TYPE_PUBLISH )
- {
- LogError( ( "Packet is not publish. Packet type: %02x.",
- ( unsigned int ) pIncomingPacket->type ) );
- status = MQTTBadParameter;
- }
- else if( pIncomingPacket->pRemainingData == NULL )
- {
- LogError( ( "Argument cannot be NULL: "
- "pIncomingPacket->pRemainingData is NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- status = deserializePublish( pIncomingPacket, pPacketId, pPublishInfo );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_DeserializeAck( const MQTTPacketInfo_t * pIncomingPacket,
- uint16_t * pPacketId,
- bool * pSessionPresent )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pIncomingPacket == NULL )
- {
- LogError( ( "pIncomingPacket cannot be NULL." ) );
- status = MQTTBadParameter;
- }
-
- /* Pointer for packet identifier cannot be NULL for packets other than
- * CONNACK and PINGRESP. */
- else if( ( pPacketId == NULL ) &&
- ( ( pIncomingPacket->type != MQTT_PACKET_TYPE_CONNACK ) &&
- ( pIncomingPacket->type != MQTT_PACKET_TYPE_PINGRESP ) ) )
- {
- LogError( ( "pPacketId cannot be NULL for packet type %02x.",
- ( unsigned int ) pIncomingPacket->type ) );
- status = MQTTBadParameter;
- }
- /* Pointer for session present cannot be NULL for CONNACK. */
- else if( ( pSessionPresent == NULL ) &&
- ( pIncomingPacket->type == MQTT_PACKET_TYPE_CONNACK ) )
- {
- LogError( ( "pSessionPresent cannot be NULL for CONNACK packet." ) );
- status = MQTTBadParameter;
- }
-
- /* Pointer for remaining data cannot be NULL for packets other
- * than PINGRESP. */
- else if( ( pIncomingPacket->pRemainingData == NULL ) &&
- ( pIncomingPacket->type != MQTT_PACKET_TYPE_PINGRESP ) )
- {
- LogError( ( "Remaining data of incoming packet is NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Make sure response packet is a valid ack. */
- switch( pIncomingPacket->type )
- {
- case MQTT_PACKET_TYPE_CONNACK:
- status = deserializeConnack( pIncomingPacket, pSessionPresent );
- break;
-
- case MQTT_PACKET_TYPE_SUBACK:
- status = deserializeSuback( pIncomingPacket, pPacketId );
- break;
-
- case MQTT_PACKET_TYPE_PINGRESP:
- status = deserializePingresp( pIncomingPacket );
- break;
-
- case MQTT_PACKET_TYPE_UNSUBACK:
- case MQTT_PACKET_TYPE_PUBACK:
- case MQTT_PACKET_TYPE_PUBREC:
- case MQTT_PACKET_TYPE_PUBREL:
- case MQTT_PACKET_TYPE_PUBCOMP:
- status = deserializeSimpleAck( pIncomingPacket, pPacketId );
- break;
-
- /* Any other packet type is invalid. */
- default:
- LogError( ( "IotMqtt_DeserializeResponse() called with unknown packet type:(%02x).",
- ( unsigned int ) pIncomingPacket->type ) );
- status = MQTTBadResponse;
- break;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_GetIncomingPacketTypeAndLength( TransportRecv_t readFunc,
- NetworkContext_t * pNetworkContext,
- MQTTPacketInfo_t * pIncomingPacket )
-{
- MQTTStatus_t status = MQTTSuccess;
- int32_t bytesReceived = 0;
-
- if( pIncomingPacket == NULL )
- {
- LogError( ( "Invalid parameter: pIncomingPacket is NULL." ) );
- status = MQTTBadParameter;
- }
- else
- {
- /* Read a single byte. */
- bytesReceived = readFunc( pNetworkContext,
- &( pIncomingPacket->type ),
- 1U );
- }
-
- if( bytesReceived == 1 )
- {
- /* Check validity. */
- if( incomingPacketValid( pIncomingPacket->type ) == true )
- {
- pIncomingPacket->remainingLength = getRemainingLength( readFunc,
- pNetworkContext );
-
- if( pIncomingPacket->remainingLength == MQTT_REMAINING_LENGTH_INVALID )
- {
- LogError( ( "Incoming packet remaining length invalid." ) );
- status = MQTTBadResponse;
- }
- }
- else
- {
- LogError( ( "Incoming packet invalid: Packet type=%u.",
- ( unsigned int ) pIncomingPacket->type ) );
- status = MQTTBadResponse;
- }
- }
- else if( ( status != MQTTBadParameter ) && ( bytesReceived == 0 ) )
- {
- status = MQTTNoDataAvailable;
- }
-
- /* If the input packet was valid, then any other number of bytes received is
- * a failure. */
- else if( status != MQTTBadParameter )
- {
- LogError( ( "A single byte was not read from the transport: "
- "transportStatus=%ld.",
- ( long int ) bytesReceived ) );
- status = MQTTRecvFailed;
- }
- else
- {
- /* Empty else MISRA 15.7 */
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_ProcessIncomingPacketTypeAndLength( const uint8_t * pBuffer,
- const size_t * pIndex,
- MQTTPacketInfo_t * pIncomingPacket )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( pIncomingPacket == NULL )
- {
- LogError( ( "Invalid parameter: pIncomingPacket is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pIndex == NULL )
- {
- LogError( ( "Invalid parameter: pIndex is NULL." ) );
- status = MQTTBadParameter;
- }
- else if( pBuffer == NULL )
- {
- LogError( ( "Invalid parameter: pBuffer is NULL." ) );
- status = MQTTBadParameter;
- }
- /* There should be at least one byte in the buffer */
- else if( *pIndex < 1U )
- {
- /* No data is available. There are 0 bytes received from the network
- * receive function. */
- status = MQTTNoDataAvailable;
- }
- else
- {
- /* At least one byte is present which should be deciphered. */
- pIncomingPacket->type = pBuffer[ 0 ];
- }
-
- if( status == MQTTSuccess )
- {
- /* Check validity. */
- if( incomingPacketValid( pIncomingPacket->type ) == true )
- {
- status = processRemainingLength( pBuffer,
- pIndex,
- pIncomingPacket );
- }
- else
- {
- LogError( ( "Incoming packet invalid: Packet type=%u.",
- ( unsigned int ) pIncomingPacket->type ) );
- status = MQTTBadResponse;
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_serializer.h b/project/coreMQTT/coreMQTT/core_mqtt_serializer.h
deleted file mode 100644
index d1b179e..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_serializer.h
+++ /dev/null
@@ -1,1306 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt_serializer.h
- * @brief User-facing functions for serializing and deserializing MQTT 3.1.1
- * packets. This header should be included for building a lighter weight MQTT
- * client than the managed CSDK MQTT library API in core_mqtt.h, by using the
- * serializer and de-serializer functions exposed in this file's API.
- */
-#ifndef CORE_MQTT_SERIALIZER_H
-#define CORE_MQTT_SERIALIZER_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON */
-
-/* MQTT_DO_NOT_USE_CUSTOM_CONFIG allows building the MQTT library
- * without a custom config. If a custom config is provided, the
- * MQTT_DO_NOT_USE_CUSTOM_CONFIG macro should not be defined. */
-#ifndef MQTT_DO_NOT_USE_CUSTOM_CONFIG
- /* Include custom config file before other headers. */
- #include "core_mqtt_config.h"
-#endif
-
-/* Include config defaults header to get default values of configs not
- * defined in core_mqtt_config.h file. */
-#include "core_mqtt_config_defaults.h"
-
-#include "transport_interface.h"
-
-/* MQTT packet types. */
-
-/**
- * @addtogroup mqtt_constants
- * @{
- */
-#define MQTT_PACKET_TYPE_CONNECT ( ( uint8_t ) 0x10U ) /**< @brief CONNECT (client-to-server). */
-#define MQTT_PACKET_TYPE_CONNACK ( ( uint8_t ) 0x20U ) /**< @brief CONNACK (server-to-client). */
-#define MQTT_PACKET_TYPE_PUBLISH ( ( uint8_t ) 0x30U ) /**< @brief PUBLISH (bidirectional). */
-#define MQTT_PACKET_TYPE_PUBACK ( ( uint8_t ) 0x40U ) /**< @brief PUBACK (bidirectional). */
-#define MQTT_PACKET_TYPE_PUBREC ( ( uint8_t ) 0x50U ) /**< @brief PUBREC (bidirectional). */
-#define MQTT_PACKET_TYPE_PUBREL ( ( uint8_t ) 0x62U ) /**< @brief PUBREL (bidirectional). */
-#define MQTT_PACKET_TYPE_PUBCOMP ( ( uint8_t ) 0x70U ) /**< @brief PUBCOMP (bidirectional). */
-#define MQTT_PACKET_TYPE_SUBSCRIBE ( ( uint8_t ) 0x82U ) /**< @brief SUBSCRIBE (client-to-server). */
-#define MQTT_PACKET_TYPE_SUBACK ( ( uint8_t ) 0x90U ) /**< @brief SUBACK (server-to-client). */
-#define MQTT_PACKET_TYPE_UNSUBSCRIBE ( ( uint8_t ) 0xA2U ) /**< @brief UNSUBSCRIBE (client-to-server). */
-#define MQTT_PACKET_TYPE_UNSUBACK ( ( uint8_t ) 0xB0U ) /**< @brief UNSUBACK (server-to-client). */
-#define MQTT_PACKET_TYPE_PINGREQ ( ( uint8_t ) 0xC0U ) /**< @brief PINGREQ (client-to-server). */
-#define MQTT_PACKET_TYPE_PINGRESP ( ( uint8_t ) 0xD0U ) /**< @brief PINGRESP (server-to-client). */
-#define MQTT_PACKET_TYPE_DISCONNECT ( ( uint8_t ) 0xE0U ) /**< @brief DISCONNECT (client-to-server). */
-/** @} */
-
-/**
- * @ingroup mqtt_constants
- * @brief The size of MQTT PUBACK, PUBREC, PUBREL, and PUBCOMP packets, per MQTT spec.
- */
-#define MQTT_PUBLISH_ACK_PACKET_SIZE ( 4UL )
-
-/* Structures defined in this file. */
-struct MQTTFixedBuffer;
-struct MQTTConnectInfo;
-struct MQTTSubscribeInfo;
-struct MQTTPublishInfo;
-struct MQTTPacketInfo;
-
-/**
- * @ingroup mqtt_enum_types
- * @brief Return codes from MQTT functions.
- */
-typedef enum MQTTStatus
-{
- MQTTSuccess = 0, /**< Function completed successfully. */
- MQTTBadParameter, /**< At least one parameter was invalid. */
- MQTTNoMemory, /**< A provided buffer was too small. */
- MQTTSendFailed, /**< The transport send function failed. */
- MQTTRecvFailed, /**< The transport receive function failed. */
- MQTTBadResponse, /**< An invalid packet was received from the server. */
- MQTTServerRefused, /**< The server refused a CONNECT or SUBSCRIBE. */
- MQTTNoDataAvailable, /**< No data available from the transport interface. */
- MQTTIllegalState, /**< An illegal state in the state record. */
- MQTTStateCollision, /**< A collision with an existing state record entry. */
- MQTTKeepAliveTimeout, /**< Timeout while waiting for PINGRESP. */
- MQTTNeedMoreBytes /**< MQTT_ProcessLoop/MQTT_ReceiveLoop has received
- incomplete data; it should be called again (probably after
- a delay). */
-} MQTTStatus_t;
-
-/**
- * @ingroup mqtt_enum_types
- * @brief MQTT Quality of Service values.
- */
-typedef enum MQTTQoS
-{
- MQTTQoS0 = 0, /**< Delivery at most once. */
- MQTTQoS1 = 1, /**< Delivery at least once. */
- MQTTQoS2 = 2 /**< Delivery exactly once. */
-} MQTTQoS_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief Buffer passed to MQTT library.
- *
- * These buffers are not copied and must remain in scope for the duration of the
- * MQTT operation.
- */
-typedef struct MQTTFixedBuffer
-{
- uint8_t * pBuffer; /**< @brief Pointer to buffer. */
- size_t size; /**< @brief Size of buffer. */
-} MQTTFixedBuffer_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief MQTT CONNECT packet parameters.
- */
-typedef struct MQTTConnectInfo
-{
- /**
- * @brief Whether to establish a new, clean session or resume a previous session.
- */
- bool cleanSession;
-
- /**
- * @brief MQTT keep alive period.
- */
- uint16_t keepAliveSeconds;
-
- /**
- * @brief MQTT client identifier. Must be unique per client.
- */
- const char * pClientIdentifier;
-
- /**
- * @brief Length of the client identifier.
- */
- uint16_t clientIdentifierLength;
-
- /**
- * @brief MQTT user name. Set to NULL if not used.
- */
- const char * pUserName;
-
- /**
- * @brief Length of MQTT user name. Set to 0 if not used.
- */
- uint16_t userNameLength;
-
- /**
- * @brief MQTT password. Set to NULL if not used.
- */
- const char * pPassword;
-
- /**
- * @brief Length of MQTT password. Set to 0 if not used.
- */
- uint16_t passwordLength;
-} MQTTConnectInfo_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief MQTT SUBSCRIBE packet parameters.
- */
-typedef struct MQTTSubscribeInfo
-{
- /**
- * @brief Quality of Service for subscription.
- */
- MQTTQoS_t qos;
-
- /**
- * @brief Topic filter to subscribe to.
- */
- const char * pTopicFilter;
-
- /**
- * @brief Length of subscription topic filter.
- */
- uint16_t topicFilterLength;
-} MQTTSubscribeInfo_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief MQTT PUBLISH packet parameters.
- */
-typedef struct MQTTPublishInfo
-{
- /**
- * @brief Quality of Service for message.
- */
- MQTTQoS_t qos;
-
- /**
- * @brief Whether this is a retained message.
- */
- bool retain;
-
- /**
- * @brief Whether this is a duplicate publish message.
- */
- bool dup;
-
- /**
- * @brief Topic name on which the message is published.
- */
- const char * pTopicName;
-
- /**
- * @brief Length of topic name.
- */
- uint16_t topicNameLength;
-
- /**
- * @brief Message payload.
- */
- const void * pPayload;
-
- /**
- * @brief Message payload length.
- */
- size_t payloadLength;
-} MQTTPublishInfo_t;
-
-/**
- * @ingroup mqtt_struct_types
- * @brief MQTT incoming packet parameters.
- */
-typedef struct MQTTPacketInfo
-{
- /**
- * @brief Type of incoming MQTT packet.
- */
- uint8_t type;
-
- /**
- * @brief Remaining serialized data in the MQTT packet.
- */
- uint8_t * pRemainingData;
-
- /**
- * @brief Length of remaining serialized data.
- */
- size_t remainingLength;
-
- /**
- * @brief The length of the MQTT header including the type and length.
- */
- size_t headerLength;
-} MQTTPacketInfo_t;
-
-/**
- * @brief Get the size and Remaining Length of an MQTT CONNECT packet.
- *
- * This function must be called before #MQTT_SerializeConnect in order to get
- * the size of the MQTT CONNECT packet that is generated from #MQTTConnectInfo_t
- * and optional #MQTTPublishInfo_t. The size of the #MQTTFixedBuffer_t supplied
- * to #MQTT_SerializeConnect must be at least @p pPacketSize. The provided
- * @p pConnectInfo and @p pWillInfo are valid for serialization with
- * #MQTT_SerializeConnect only if this function returns #MQTTSuccess. The
- * remaining length returned in @p pRemainingLength and the packet size returned
- * in @p pPacketSize are valid only if this function returns #MQTTSuccess.
- *
- * @param[in] pConnectInfo MQTT CONNECT packet parameters.
- * @param[in] pWillInfo Last Will and Testament. Pass NULL if not used.
- * @param[out] pRemainingLength The Remaining Length of the MQTT CONNECT packet.
- * @param[out] pPacketSize The total size of the MQTT CONNECT packet.
- *
- * @return #MQTTBadParameter if the packet would exceed the size allowed by the
- * MQTT spec; #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTConnectInfo_t connectInfo = { 0 };
- * MQTTPublishInfo_t willInfo = { 0 };
- * size_t remainingLength = 0, packetSize = 0;
- *
- * // Initialize the connection info, the details are out of scope for this example.
- * initializeConnectInfo( &connectInfo );
- *
- * // Initialize the optional will info, the details are out of scope for this example.
- * initializeWillInfo( &willInfo );
- *
- * // Get the size requirement for the connect packet.
- * status = MQTT_GetConnectPacketSize(
- * &connectInfo, &willInfo, &remainingLength, &packetSize
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The application should allocate or use a static #MQTTFixedBuffer_t
- * // of size >= packetSize to serialize the connect request.
- * }
- * @endcode
- */
-/* @[declare_mqtt_getconnectpacketsize] */
-MQTTStatus_t MQTT_GetConnectPacketSize( const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t * pRemainingLength,
- size_t * pPacketSize );
-/* @[declare_mqtt_getconnectpacketsize] */
-
-/**
- * @brief Serialize an MQTT CONNECT packet in the given fixed buffer @p pFixedBuffer.
- *
- * #MQTT_GetConnectPacketSize should be called with @p pConnectInfo and
- * @p pWillInfo before invoking this function to get the size of the required
- * #MQTTFixedBuffer_t and @p remainingLength. The @p remainingLength must be
- * the same as returned by #MQTT_GetConnectPacketSize. The #MQTTFixedBuffer_t
- * must be at least as large as the size returned by #MQTT_GetConnectPacketSize.
- *
- * @param[in] pConnectInfo MQTT CONNECT packet parameters.
- * @param[in] pWillInfo Last Will and Testament. Pass NULL if not used.
- * @param[in] remainingLength Remaining Length provided by #MQTT_GetConnectPacketSize.
- * @param[out] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTConnectInfo_t connectInfo = { 0 };
- * MQTTPublishInfo_t willInfo = { 0 };
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- * size_t remainingLength = 0, packetSize = 0;
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // Assume connectInfo and willInfo are initialized. Get the size requirement for
- * // the connect packet.
- * status = MQTT_GetConnectPacketSize(
- * &connectInfo, &willInfo, &remainingLength, &packetSize
- * );
- * assert( status == MQTTSuccess );
- * assert( packetSize <= BUFFER_SIZE );
- *
- * // Serialize the connect packet into the fixed buffer.
- * status = MQTT_SerializeConnect( &connectInfo, &willInfo, remainingLength, &fixedBuffer );
- *
- * if( status == MQTTSuccess )
- * {
- * // The connect packet can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializeconnect] */
-MQTTStatus_t MQTT_SerializeConnect( const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer );
-/* @[declare_mqtt_serializeconnect] */
-
-/**
- * @brief Get packet size and Remaining Length of an MQTT SUBSCRIBE packet.
- *
- * This function must be called before #MQTT_SerializeSubscribe in order to get
- * the size of the MQTT SUBSCRIBE packet that is generated from the list of
- * #MQTTSubscribeInfo_t. The size of the #MQTTFixedBuffer_t supplied
- * to #MQTT_SerializeSubscribe must be at least @p pPacketSize. The provided
- * @p pSubscriptionList is valid for serialization with #MQTT_SerializeSubscribe
- * only if this function returns #MQTTSuccess. The remaining length returned in
- * @p pRemainingLength and the packet size returned in @p pPacketSize are valid
- * only if this function returns #MQTTSuccess.
- *
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[out] pRemainingLength The Remaining Length of the MQTT SUBSCRIBE packet.
- * @param[out] pPacketSize The total size of the MQTT SUBSCRIBE packet.
- *
- * @return #MQTTBadParameter if the packet would exceed the size allowed by the
- * MQTT spec; #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTSubscribeInfo_t subscriptionList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 };
- * size_t remainingLength = 0, packetSize = 0;
- * // This is assumed to be a list of filters we want to subscribe to.
- * const char * filters[ NUMBER_OF_SUBSCRIPTIONS ];
- *
- * // Set each subscription.
- * for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ )
- * {
- * subscriptionList[ i ].qos = MQTTQoS0;
- * // Each subscription needs a topic filter.
- * subscriptionList[ i ].pTopicFilter = filters[ i ];
- * subscriptionList[ i ].topicFilterLength = strlen( filters[ i ] );
- * }
- *
- * // Get the size requirement for the subscribe packet.
- * status = MQTT_GetSubscribePacketSize(
- * &subscriptionList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, &remainingLength, &packetSize
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The application should allocate or use a static #MQTTFixedBuffer_t
- * // of size >= packetSize to serialize the subscribe request.
- * }
- * @endcode
- */
-/* @[declare_mqtt_getsubscribepacketsize] */
-MQTTStatus_t MQTT_GetSubscribePacketSize( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- size_t * pRemainingLength,
- size_t * pPacketSize );
-/* @[declare_mqtt_getsubscribepacketsize] */
-
-/**
- * @brief Serialize an MQTT SUBSCRIBE packet in the given buffer.
- *
- * #MQTT_GetSubscribePacketSize should be called with @p pSubscriptionList
- * before invoking this function to get the size of the required
- * #MQTTFixedBuffer_t and @p remainingLength. The @p remainingLength must be
- * the same as returned by #MQTT_GetSubscribePacketSize. The #MQTTFixedBuffer_t
- * must be at least as large as the size returned by #MQTT_GetSubscribePacketSize.
- *
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[in] packetId packet ID generated by #MQTT_GetPacketId.
- * @param[in] remainingLength Remaining Length provided by #MQTT_GetSubscribePacketSize.
- * @param[out] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTSubscribeInfo_t subscriptionList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 };
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- * size_t remainingLength = 0, packetSize = 0;
- * uint16_t packetId;
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // Function to return a valid, unused packet identifier. The details are out of
- * // scope for this example.
- * packetId = getNewPacketId();
- *
- * // Assume subscriptionList has been initialized. Get the subscribe packet size.
- * status = MQTT_GetSubscribePacketSize(
- * &subscriptionList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, &remainingLength, &packetSize
- * );
- * assert( status == MQTTSuccess );
- * assert( packetSize <= BUFFER_SIZE );
- *
- * // Serialize the subscribe packet into the fixed buffer.
- * status = MQTT_SerializeSubscribe(
- * &subscriptionList[ 0 ],
- * NUMBER_OF_SUBSCRIPTIONS,
- * packetId,
- * remainingLength,
- * &fixedBuffer
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The subscribe packet can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializesubscribe] */
-MQTTStatus_t MQTT_SerializeSubscribe( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer );
-/* @[declare_mqtt_serializesubscribe] */
-
-/**
- * @brief Get packet size and Remaining Length of an MQTT UNSUBSCRIBE packet.
- *
- * This function must be called before #MQTT_SerializeUnsubscribe in order to
- * get the size of the MQTT UNSUBSCRIBE packet that is generated from the list
- * of #MQTTSubscribeInfo_t. The size of the #MQTTFixedBuffer_t supplied
- * to #MQTT_SerializeUnsubscribe must be at least @p pPacketSize. The provided
- * @p pSubscriptionList is valid for serialization with #MQTT_SerializeUnsubscribe
- * only if this function returns #MQTTSuccess. The remaining length returned in
- * @p pRemainingLength and the packet size returned in @p pPacketSize are valid
- * only if this function returns #MQTTSuccess.
- *
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[out] pRemainingLength The Remaining Length of the MQTT UNSUBSCRIBE packet.
- * @param[out] pPacketSize The total size of the MQTT UNSUBSCRIBE packet.
- *
- * @return #MQTTBadParameter if the packet would exceed the size allowed by the
- * MQTT spec; #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTSubscribeInfo_t subscriptionList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 };
- * size_t remainingLength = 0, packetSize = 0;
- *
- * // Initialize the subscribe info. The details are out of scope for this example.
- * initializeSubscribeInfo( &subscriptionList[ 0 ] );
- *
- * // Get the size requirement for the unsubscribe packet.
- * status = MQTT_GetUnsubscribePacketSize(
- * &subscriptionList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, &remainingLength, &packetSize
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The application should allocate or use a static #MQTTFixedBuffer_t
- * // of size >= packetSize to serialize the unsubscribe request.
- * }
- * @endcode
- */
-/* @[declare_mqtt_getunsubscribepacketsize] */
-MQTTStatus_t MQTT_GetUnsubscribePacketSize( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- size_t * pRemainingLength,
- size_t * pPacketSize );
-/* @[declare_mqtt_getunsubscribepacketsize] */
-
-/**
- * @brief Serialize an MQTT UNSUBSCRIBE packet in the given buffer.
- *
- * #MQTT_GetUnsubscribePacketSize should be called with @p pSubscriptionList
- * before invoking this function to get the size of the required
- * #MQTTFixedBuffer_t and @p remainingLength. The @p remainingLength must be
- * the same as returned by #MQTT_GetUnsubscribePacketSize. The #MQTTFixedBuffer_t
- * must be at least as large as the size returned by #MQTT_GetUnsubscribePacketSize.
- *
- * @param[in] pSubscriptionList List of MQTT subscription info.
- * @param[in] subscriptionCount The number of elements in pSubscriptionList.
- * @param[in] packetId packet ID generated by #MQTT_GetPacketId.
- * @param[in] remainingLength Remaining Length provided by #MQTT_GetUnsubscribePacketSize.
- * @param[out] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTSubscribeInfo_t subscriptionList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 };
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- * size_t remainingLength = 0, packetSize = 0;
- * uint16_t packetId;
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // Function to return a valid, unused packet identifier. The details are out of
- * // scope for this example.
- * packetId = getNewPacketId();
- *
- * // Assume subscriptionList has been initialized. Get the unsubscribe packet size.
- * status = MQTT_GetUnsubscribePacketSize(
- * &subscriptionList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, &remainingLength, &packetSize
- * );
- * assert( status == MQTTSuccess );
- * assert( packetSize <= BUFFER_SIZE );
- *
- * // Serialize the unsubscribe packet into the fixed buffer.
- * status = MQTT_SerializeUnsubscribe(
- * &subscriptionList[ 0 ],
- * NUMBER_OF_SUBSCRIPTIONS,
- * packetId,
- * remainingLength,
- * &fixedBuffer
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The unsubscribe packet can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializeunsubscribe] */
-MQTTStatus_t MQTT_SerializeUnsubscribe( const MQTTSubscribeInfo_t * pSubscriptionList,
- size_t subscriptionCount,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer );
-/* @[declare_mqtt_serializeunsubscribe] */
-
-/**
- * @brief Get the packet size and remaining length of an MQTT PUBLISH packet.
- *
- * This function must be called before #MQTT_SerializePublish in order to get
- * the size of the MQTT PUBLISH packet that is generated from #MQTTPublishInfo_t.
- * The size of the #MQTTFixedBuffer_t supplied to #MQTT_SerializePublish must be
- * at least @p pPacketSize. The provided @p pPublishInfo is valid for
- * serialization with #MQTT_SerializePublish only if this function returns
- * #MQTTSuccess. The remaining length returned in @p pRemainingLength and the
- * packet size returned in @p pPacketSize are valid only if this function
- * returns #MQTTSuccess.
- *
- * @param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @param[out] pRemainingLength The Remaining Length of the MQTT PUBLISH packet.
- * @param[out] pPacketSize The total size of the MQTT PUBLISH packet.
- *
- * @return #MQTTBadParameter if the packet would exceed the size allowed by the
- * MQTT spec or if invalid parameters are passed; #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTPublishInfo_t publishInfo = { 0 };
- * size_t remainingLength = 0, packetSize = 0;
- *
- * // Initialize the publish info.
- * publishInfo.qos = MQTTQoS0;
- * publishInfo.pTopicName = "/some/topic/name";
- * publishInfo.topicNameLength = strlen( publishInfo.pTopicName );
- * publishInfo.pPayload = "Hello World!";
- * publishInfo.payloadLength = strlen( "Hello World!" );
- *
- * // Get the size requirement for the publish packet.
- * status = MQTT_GetPublishPacketSize(
- * &publishInfo, &remainingLength, &packetSize
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The application should allocate or use a static #MQTTFixedBuffer_t
- * // of size >= packetSize to serialize the publish.
- * }
- * @endcode
- */
-/* @[declare_mqtt_getpublishpacketsize] */
-MQTTStatus_t MQTT_GetPublishPacketSize( const MQTTPublishInfo_t * pPublishInfo,
- size_t * pRemainingLength,
- size_t * pPacketSize );
-/* @[declare_mqtt_getpublishpacketsize] */
-
-/**
- * @brief Serialize an MQTT PUBLISH packet in the given buffer.
- *
- * This function will serialize complete MQTT PUBLISH packet into
- * the given buffer. If the PUBLISH payload can be sent separately,
- * consider using #MQTT_SerializePublishHeader, which will serialize
- * only the PUBLISH header into the buffer.
- *
- * #MQTT_GetPublishPacketSize should be called with @p pPublishInfo before
- * invoking this function to get the size of the required #MQTTFixedBuffer_t and
- * @p remainingLength. The @p remainingLength must be the same as returned by
- * #MQTT_GetPublishPacketSize. The #MQTTFixedBuffer_t must be at least as large
- * as the size returned by #MQTT_GetPublishPacketSize.
- *
- * @param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @param[in] packetId packet ID generated by #MQTT_GetPacketId.
- * @param[in] remainingLength Remaining Length provided by #MQTT_GetPublishPacketSize.
- * @param[out] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTPublishInfo_t publishInfo = { 0 };
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- * size_t remainingLength = 0, packetSize = 0;
- * uint16_t packetId;
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // A packet identifier is unused for QoS 0 publishes. Otherwise, a valid, unused packet
- * // identifier must be used.
- * packetId = 0;
- *
- * // Assume publishInfo has been initialized. Get publish packet size.
- * status = MQTT_GetPublishPacketSize(
- * &publishInfo, &remainingLength, &packetSize
- * );
- * assert( status == MQTTSuccess );
- * assert( packetSize <= BUFFER_SIZE );
- *
- * // Serialize the publish packet into the fixed buffer.
- * status = MQTT_SerializePublish(
- * &publishInfo,
- * packetId,
- * remainingLength,
- * &fixedBuffer
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The publish packet can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializepublish] */
-MQTTStatus_t MQTT_SerializePublish( const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer );
-/* @[declare_mqtt_serializepublish] */
-
-/**
- * @brief Serialize an MQTT PUBLISH packet header without the topic string in the
- * given buffer. This function will add the topic string length to the provided
- * buffer. This helps reduce an unnecessary copy of the topic string into the
- * buffer.
- *
- * @param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @param[in] remainingLength Remaining Length provided by #MQTT_GetPublishPacketSize.
- * @param[out] pBuffer Buffer for packet serialization.
- * @param[out] headerSize Size of the serialized MQTT PUBLISH header.
- *
- * @return #MQTTSuccess if the serialization is successful. Otherwise, #MQTTBadParameter.
- */
-MQTTStatus_t MQTT_SerializePublishHeaderWithoutTopic( const MQTTPublishInfo_t * pPublishInfo,
- size_t remainingLength,
- uint8_t * pBuffer,
- size_t * headerSize );
-
-/**
- * @brief Serialize an MQTT PUBLISH packet header in the given buffer.
- *
- * This function serializes PUBLISH header in to the given buffer. The payload
- * for PUBLISH will not be copied over to the buffer. This will help reduce
- * the memory needed for the buffer and avoid an unwanted copy operation of the
- * PUBLISH payload into the buffer. If the payload also would need to be part of
- * the serialized buffer, consider using #MQTT_SerializePublish.
- *
- * #MQTT_GetPublishPacketSize should be called with @p pPublishInfo before
- * invoking this function to get the size of the required #MQTTFixedBuffer_t and
- * @p remainingLength. The @p remainingLength must be the same as returned by
- * #MQTT_GetPublishPacketSize. The #MQTTFixedBuffer_t must be at least as large
- * as the size returned by #MQTT_GetPublishPacketSize.
- *
- * @param[in] pPublishInfo MQTT PUBLISH packet parameters.
- * @param[in] packetId packet ID generated by #MQTT_GetPacketId.
- * @param[in] remainingLength Remaining Length provided by #MQTT_GetPublishPacketSize.
- * @param[out] pFixedBuffer Buffer for packet serialization.
- * @param[out] pHeaderSize Size of the serialized MQTT PUBLISH header.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTPublishInfo_t publishInfo = { 0 };
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- * size_t remainingLength = 0, packetSize = 0, headerSize = 0;
- * uint16_t packetId;
- * int32_t bytesSent;
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // A packet identifier is unused for QoS 0 publishes. Otherwise, a valid, unused packet
- * // identifier must be used.
- * packetId = 0;
- *
- * // Assume publishInfo has been initialized. Get the publish packet size.
- * status = MQTT_GetPublishPacketSize(
- * &publishInfo, &remainingLength, &packetSize
- * );
- * assert( status == MQTTSuccess );
- * // The payload will not be serialized, so the the fixed buffer does not need to hold it.
- * assert( ( packetSize - publishInfo.payloadLength ) <= BUFFER_SIZE );
- *
- * // Serialize the publish packet header into the fixed buffer.
- * status = MQTT_SerializePublishHeader(
- * &publishInfo,
- * packetId,
- * remainingLength,
- * &fixedBuffer,
- * &headerSize
- * );
- *
- * if( status == MQTTSuccess )
- * {
- * // The publish header and payload can now be sent to the broker.
- * // mqttSocket here is a socket descriptor created and connected to the MQTT
- * // broker outside of this function.
- * bytesSent = send( mqttSocket, ( void * ) fixedBuffer.pBuffer, headerSize, 0 );
- * assert( bytesSent == headerSize );
- * bytesSent = send( mqttSocket, publishInfo.pPayload, publishInfo.payloadLength, 0 );
- * assert( bytesSent == publishInfo.payloadLength );
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializepublishheader] */
-MQTTStatus_t MQTT_SerializePublishHeader( const MQTTPublishInfo_t * pPublishInfo,
- uint16_t packetId,
- size_t remainingLength,
- const MQTTFixedBuffer_t * pFixedBuffer,
- size_t * pHeaderSize );
-/* @[declare_mqtt_serializepublishheader] */
-
-/**
- * @brief Serialize an MQTT PUBACK, PUBREC, PUBREL, or PUBCOMP into the given
- * buffer.
- *
- * @param[out] pFixedBuffer Buffer for packet serialization.
- * @param[in] packetType Byte of the corresponding packet fixed header per the
- * MQTT spec.
- * @param[in] packetId Packet ID of the publish.
- *
- * @return #MQTTBadParameter, #MQTTNoMemory, or #MQTTSuccess.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- * uint16_t packetId;
- * uint8_t packetType;
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- * // The fixed buffer must be large enough to hold 4 bytes.
- * assert( BUFFER_SIZE >= MQTT_PUBLISH_ACK_PACKET_SIZE );
- *
- * // The packet ID must be the same as the original publish packet.
- * packetId = publishPacketId;
- *
- * // The byte representing a packet of type ACK. This function accepts PUBACK, PUBREC, PUBREL, or PUBCOMP.
- * packetType = MQTT_PACKET_TYPE_PUBACK;
- *
- * // Serialize the publish acknowledgment into the fixed buffer.
- * status = MQTT_SerializeAck( &fixedBuffer, packetType, packetId );
- *
- * if( status == MQTTSuccess )
- * {
- * // The publish acknowledgment can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializeack] */
-MQTTStatus_t MQTT_SerializeAck( const MQTTFixedBuffer_t * pFixedBuffer,
- uint8_t packetType,
- uint16_t packetId );
-/* @[declare_mqtt_serializeack] */
-
-/**
- * @brief Get the size of an MQTT DISCONNECT packet.
- *
- * @param[out] pPacketSize The size of the MQTT DISCONNECT packet.
- *
- * @return #MQTTSuccess, or #MQTTBadParameter if @p pPacketSize is NULL.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * size_t packetSize = 0;
- *
- * // Get the size requirement for the disconnect packet.
- * status = MQTT_GetDisconnectPacketSize( &packetSize );
- * assert( status == MQTTSuccess );
- * assert( packetSize == 2 );
- *
- * // The application should allocate or use a static #MQTTFixedBuffer_t of
- * // size >= 2 to serialize the disconnect packet.
- *
- * @endcode
- */
-/* @[declare_mqtt_getdisconnectpacketsize] */
-MQTTStatus_t MQTT_GetDisconnectPacketSize( size_t * pPacketSize );
-/* @[declare_mqtt_getdisconnectpacketsize] */
-
-/**
- * @brief Serialize an MQTT DISCONNECT packet into the given buffer.
- *
- * The input #MQTTFixedBuffer_t.size must be at least as large as the size
- * returned by #MQTT_GetDisconnectPacketSize.
- *
- * @param[out] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // Get the disconnect packet size.
- * status = MQTT_GetDisconnectPacketSize( &packetSize );
- * assert( status == MQTTSuccess );
- * assert( packetSize <= BUFFER_SIZE );
- *
- * // Serialize the disconnect into the fixed buffer.
- * status = MQTT_SerializeDisconnect( &fixedBuffer );
- *
- * if( status == MQTTSuccess )
- * {
- * // The disconnect packet can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializedisconnect] */
-MQTTStatus_t MQTT_SerializeDisconnect( const MQTTFixedBuffer_t * pFixedBuffer );
-/* @[declare_mqtt_serializedisconnect] */
-
-/**
- * @brief Get the size of an MQTT PINGREQ packet.
- *
- * @param[out] pPacketSize The size of the MQTT PINGREQ packet.
- *
- * @return #MQTTSuccess or #MQTTBadParameter if pPacketSize is NULL.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * size_t packetSize = 0;
- *
- * // Get the size requirement for the ping request packet.
- * status = MQTT_GetPingreqPacketSize( &packetSize );
- * assert( status == MQTTSuccess );
- * assert( packetSize == 2 );
- *
- * // The application should allocate or use a static #MQTTFixedBuffer_t of
- * // size >= 2 to serialize the ping request.
- *
- * @endcode
- */
-/* @[declare_mqtt_getpingreqpacketsize] */
-MQTTStatus_t MQTT_GetPingreqPacketSize( size_t * pPacketSize );
-/* @[declare_mqtt_getpingreqpacketsize] */
-
-/**
- * @brief Serialize an MQTT PINGREQ packet into the given buffer.
- *
- * The input #MQTTFixedBuffer_t.size must be at least as large as the size
- * returned by #MQTT_GetPingreqPacketSize.
- *
- * @param[out] pFixedBuffer Buffer for packet serialization.
- *
- * @return #MQTTNoMemory if pFixedBuffer is too small to hold the MQTT packet;
- * #MQTTBadParameter if invalid parameters are passed;
- * #MQTTSuccess otherwise.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTFixedBuffer_t fixedBuffer;
- * uint8_t buffer[ BUFFER_SIZE ];
- *
- * fixedBuffer.pBuffer = buffer;
- * fixedBuffer.size = BUFFER_SIZE;
- *
- * // Get the ping request packet size.
- * status = MQTT_GetPingreqPacketSize( &packetSize );
- * assert( status == MQTTSuccess );
- * assert( packetSize <= BUFFER_SIZE );
- *
- * // Serialize the ping request into the fixed buffer.
- * status = MQTT_SerializePingreq( &fixedBuffer );
- *
- * if( status == MQTTSuccess )
- * {
- * // The ping request can now be sent to the broker.
- * }
- * @endcode
- */
-/* @[declare_mqtt_serializepingreq] */
-MQTTStatus_t MQTT_SerializePingreq( const MQTTFixedBuffer_t * pFixedBuffer );
-/* @[declare_mqtt_serializepingreq] */
-
-/**
- * @brief Deserialize an MQTT PUBLISH packet.
- *
- * @param[in] pIncomingPacket #MQTTPacketInfo_t containing the buffer.
- * @param[out] pPacketId The packet ID obtained from the buffer.
- * @param[out] pPublishInfo Struct containing information about the publish.
- *
- * @return #MQTTBadParameter, #MQTTBadResponse, or #MQTTSuccess.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // TransportRecv_t function for reading from the network.
- * int32_t socket_recv(
- * NetworkContext_t * pNetworkContext,
- * void * pBuffer,
- * size_t bytesToRecv
- * );
- * // Some context to be used with the above transport receive function.
- * NetworkContext_t networkContext;
- *
- * // Other variables used in this example.
- * MQTTStatus_t status;
- * MQTTPacketInfo_t incomingPacket;
- * MQTTPublishInfo_t publishInfo = { 0 };
- * uint16_t packetId;
- *
- * int32_t bytesRecvd;
- * // A buffer to hold remaining data of the incoming packet.
- * uint8_t buffer[ BUFFER_SIZE ];
- *
- * // Populate all fields of the incoming packet.
- * status = MQTT_GetIncomingPacketTypeAndLength(
- * socket_recv,
- * &networkContext,
- * &incomingPacket
- * );
- * assert( status == MQTTSuccess );
- * assert( incomingPacket.remainingLength <= BUFFER_SIZE );
- * bytesRecvd = socket_recv(
- * &networkContext,
- * ( void * ) buffer,
- * incomingPacket.remainingLength
- * );
- * incomingPacket.pRemainingData = buffer;
- *
- * // Deserialize the publish information if the incoming packet is a publish.
- * if( ( incomingPacket.type & 0xF0 ) == MQTT_PACKET_TYPE_PUBLISH )
- * {
- * status = MQTT_DeserializePublish( &incomingPacket, &packetId, &publishInfo );
- * if( status == MQTTSuccess )
- * {
- * // The deserialized publish information can now be used from `publishInfo`.
- * }
- * }
- * @endcode
- */
-/* @[declare_mqtt_deserializepublish] */
-MQTTStatus_t MQTT_DeserializePublish( const MQTTPacketInfo_t * pIncomingPacket,
- uint16_t * pPacketId,
- MQTTPublishInfo_t * pPublishInfo );
-/* @[declare_mqtt_deserializepublish] */
-
-/**
- * @brief Deserialize an MQTT CONNACK, SUBACK, UNSUBACK, PUBACK, PUBREC, PUBREL,
- * PUBCOMP, or PINGRESP.
- *
- * @param[in] pIncomingPacket #MQTTPacketInfo_t containing the buffer.
- * @param[out] pPacketId The packet ID of obtained from the buffer. Not used
- * in CONNACK or PINGRESP.
- * @param[out] pSessionPresent Boolean flag from a CONNACK indicating present session.
- *
- * @return #MQTTBadParameter, #MQTTBadResponse, #MQTTServerRefused, or #MQTTSuccess.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTPacketInfo_t incomingPacket;
- * // Used for SUBACK, UNSUBACK, PUBACK, PUBREC, PUBREL, and PUBCOMP.
- * uint16_t packetId;
- * // Used for CONNACK.
- * bool sessionPresent;
- *
- * // Receive an incoming packet and populate all fields. The details are out of scope
- * // for this example.
- * receiveIncomingPacket( &incomingPacket );
- *
- * // Deserialize ack information if the incoming packet is not a publish.
- * if( ( incomingPacket.type & 0xF0 ) != MQTT_PACKET_TYPE_PUBLISH )
- * {
- * status = MQTT_DeserializeAck( &incomingPacket, &packetId, &sessionPresent );
- * if( status == MQTTSuccess )
- * {
- * // The packet ID or session present flag information is available. For
- * // ping response packets, the only information is the status code.
- * }
- * }
- * @endcode
- */
-/* @[declare_mqtt_deserializeack] */
-MQTTStatus_t MQTT_DeserializeAck( const MQTTPacketInfo_t * pIncomingPacket,
- uint16_t * pPacketId,
- bool * pSessionPresent );
-/* @[declare_mqtt_deserializeack] */
-
-/**
- * @brief Extract the MQTT packet type and length from incoming packet.
- *
- * This function must be called for every incoming packet to retrieve the
- * #MQTTPacketInfo_t.type and #MQTTPacketInfo_t.remainingLength. A
- * #MQTTPacketInfo_t is not valid until this routine has been invoked.
- *
- * @param[in] readFunc Transport layer read function pointer.
- * @param[in] pNetworkContext The network context pointer provided by the application.
- * @param[out] pIncomingPacket Pointer to MQTTPacketInfo_t structure. This is
- * where type, remaining length and packet identifier are stored.
- *
- * @return #MQTTSuccess on successful extraction of type and length,
- * #MQTTBadParameter if @p pIncomingPacket is invalid,
- * #MQTTRecvFailed on transport receive failure,
- * #MQTTBadResponse if an invalid packet is read, and
- * #MQTTNoDataAvailable if there is nothing to read.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // TransportRecv_t function for reading from the network.
- * int32_t socket_recv(
- * NetworkContext_t * pNetworkContext,
- * void * pBuffer,
- * size_t bytesToRecv
- * );
- * // Some context to be used with above transport receive function.
- * NetworkContext_t networkContext;
- *
- * // Struct to hold the incoming packet information.
- * MQTTPacketInfo_t incomingPacket;
- * MQTTStatus_t status = MQTTSuccess;
- * int32_t bytesRecvd;
- * // Buffer to hold the remaining data of the incoming packet.
- * uint8_t buffer[ BUFFER_SIZE ];
- *
- * // Loop until data is available to be received.
- * do{
- * status = MQTT_GetIncomingPacketTypeAndLength(
- * socket_recv,
- * &networkContext,
- * &incomingPacket
- * );
- * } while( status == MQTTNoDataAvailable );
- *
- * assert( status == MQTTSuccess );
- *
- * // Receive the rest of the incoming packet.
- * assert( incomingPacket.remainingLength <= BUFFER_SIZE );
- * bytesRecvd = socket_recv(
- * &networkContext,
- * ( void * ) buffer,
- * incomingPacket.remainingLength
- * );
- *
- * // Set the remaining data field.
- * incomingPacket.pRemainingData = buffer;
- * @endcode
- */
-/* @[declare_mqtt_getincomingpackettypeandlength] */
-MQTTStatus_t MQTT_GetIncomingPacketTypeAndLength( TransportRecv_t readFunc,
- NetworkContext_t * pNetworkContext,
- MQTTPacketInfo_t * pIncomingPacket );
-/* @[declare_mqtt_getincomingpackettypeandlength] */
-
-/**
- * @brief Extract the MQTT packet type and length from incoming packet.
- *
- * This function must be called for every incoming packet to retrieve the
- * #MQTTPacketInfo_t.type and #MQTTPacketInfo_t.remainingLength. A
- * #MQTTPacketInfo_t is not valid until this routine has been invoked.
- *
- * @param[in] pBuffer The buffer holding the raw data to be processed
- * @param[in] pIndex Pointer to the index within the buffer to marking the end
- * of raw data available.
- * @param[out] pIncomingPacket Structure used to hold the fields of the
- * incoming packet.
- *
- * @return #MQTTSuccess on successful extraction of type and length,
- * #MQTTBadParameter if @p pIncomingPacket is invalid,
- * #MQTTBadResponse if an invalid packet is read, and
- * #MQTTNoDataAvailable if there is nothing to read.
- */
- /* @[declare_mqtt_processincomingpackettypeandlength] */
-MQTTStatus_t MQTT_ProcessIncomingPacketTypeAndLength( const uint8_t * pBuffer,
- const size_t * pIndex,
- MQTTPacketInfo_t * pIncomingPacket );
-/* @[declare_mqtt_processincomingpackettypeandlength] */
-
-/**
- * @fn uint8_t * MQTT_SerializeConnectFixedHeader( uint8_t * pIndex, const MQTTConnectInfo_t * pConnectInfo, const MQTTPublishInfo_t * pWillInfo, size_t remainingLength );
- * @brief Serialize the fixed part of the connect packet header.
- *
- * @param[out] pIndex Pointer to the buffer where the header is to
- * be serialized.
- * @param[in] pConnectInfo The connect information.
- * @param[in] pWillInfo The last will and testament information.
- * @param[in] remainingLength The remaining length of the packet to be
- * serialized.
- *
- * @return A pointer to the end of the encoded string.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-uint8_t * MQTT_SerializeConnectFixedHeader( uint8_t * pIndex,
- const MQTTConnectInfo_t * pConnectInfo,
- const MQTTPublishInfo_t * pWillInfo,
- size_t remainingLength );
-/** @endcond */
-
-/**
- * @fn uint8_t * MQTT_SerializeSubscribeHeader( size_t remainingLength, uint8_t * pIndex, uint16_t packetId );
- * @brief Serialize the fixed part of the subscribe packet header.
- *
- * @param[in] remainingLength The remaining length of the packet to be
- * serialized.
- * @param[in] pIndex Pointer to the buffer where the header is to
- * be serialized.
- * @param[in] packetId The packet ID to be serialized.
- *
- * @return A pointer to the end of the encoded string.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-uint8_t * MQTT_SerializeSubscribeHeader( size_t remainingLength,
- uint8_t * pIndex,
- uint16_t packetId );
-/** @endcond */
-
-/**
- * @fn uint8_t * MQTT_SerializeUnsubscribeHeader( size_t remainingLength, uint8_t * pIndex, uint16_t packetId );
- * @brief Serialize the fixed part of the unsubscribe packet header.
- *
- * @param[in] remainingLength The remaining length of the packet to be
- * serialized.
- * @param[in] pIndex Pointer to the buffer where the header is to
- * be serialized.
- * @param[in] packetId The packet ID to be serialized.
- *
- * @return A pointer to the end of the encoded string.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-uint8_t * MQTT_SerializeUnsubscribeHeader( size_t remainingLength,
- uint8_t * pIndex,
- uint16_t packetId );
-/** @endcond */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_MQTT_SERIALIZER_H */
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_state.c b/project/coreMQTT/coreMQTT/core_mqtt_state.c
deleted file mode 100644
index 8ad3f2b..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_state.c
+++ /dev/null
@@ -1,1214 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt_state.c
- * @brief Implements the functions in core_mqtt_state.h.
- */
-#include <assert.h>
-#include <string.h>
-#include "core_mqtt_state.h"
-
-/* Include config defaults header to get default values of configs. */
-#include "core_mqtt_config_defaults.h"
-
-#include "core_mqtt_default_logging.h"
-
-/*-----------------------------------------------------------*/
-
-/**
- * @brief A global static variable used to generate the macro
- * #MQTT_INVALID_STATE_COUNT of size_t length.
- */
-static const size_t ZERO_SIZE_T = 0U;
-
-/**
- * @brief This macro depicts the invalid value for the state publishes.
- */
-#define MQTT_INVALID_STATE_COUNT ( ~ZERO_SIZE_T )
-
-/**
- * @brief Create a 16-bit bitmap with bit set at specified position.
- *
- * @param[in] position The position at which the bit need to be set.
- */
-#define UINT16_BITMAP_BIT_SET_AT( position ) ( ( uint16_t ) 0x01U << ( ( uint16_t ) position ) )
-
-/**
- * @brief Set a bit in an 16-bit unsigned integer.
- *
- * @param[in] x The 16-bit unsigned integer to set a bit.
- * @param[in] position The position at which the bit need to be set.
- */
-#define UINT16_SET_BIT( x, position ) ( ( x ) = ( uint16_t ) ( ( x ) | ( UINT16_BITMAP_BIT_SET_AT( position ) ) ) )
-
-/**
- * @brief Macro for checking if a bit is set in a 16-bit unsigned integer.
- *
- * @param[in] x The unsigned 16-bit integer to check.
- * @param[in] position Which bit to check.
- */
-#define UINT16_CHECK_BIT( x, position ) ( ( ( x ) & ( UINT16_BITMAP_BIT_SET_AT( position ) ) ) == ( UINT16_BITMAP_BIT_SET_AT( position ) ) )
-
-/*-----------------------------------------------------------*/
-
-/**
- * @brief Test if a transition to new state is possible, when dealing with PUBLISHes.
- *
- * @param[in] currentState The current state.
- * @param[in] newState State to transition to.
- * @param[in] opType Reserve, Send, or Receive.
- * @param[in] qos 0, 1, or 2.
- *
- * @note This function does not validate the current state, or the new state
- * based on either the operation type or QoS. It assumes the new state is valid
- * given the opType and QoS, which will be the case if calculated by
- * MQTT_CalculateStatePublish().
- *
- * @return `true` if transition is possible, else `false`
- */
-static bool validateTransitionPublish( MQTTPublishState_t currentState,
- MQTTPublishState_t newState,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos );
-
-/**
- * @brief Test if a transition to a new state is possible, when dealing with acks.
- *
- * @param[in] currentState The current state.
- * @param[in] newState State to transition to.
- *
- * @return `true` if transition is possible, else `false`.
- */
-static bool validateTransitionAck( MQTTPublishState_t currentState,
- MQTTPublishState_t newState );
-
-/**
- * @brief Test if the publish corresponding to an ack is outgoing or incoming.
- *
- * @param[in] packetType PUBACK, PUBREC, PUBREL, or PUBCOMP.
- * @param[in] opType Send, or Receive.
- *
- * @return `true` if corresponds to outgoing publish, else `false`.
- */
-static bool isPublishOutgoing( MQTTPubAckType_t packetType,
- MQTTStateOperation_t opType );
-
-/**
- * @brief Find a packet ID in the state record.
- *
- * @param[in] records State record array.
- * @param[in] recordCount Length of record array.
- * @param[in] packetId packet ID to search for.
- * @param[out] pQos QoS retrieved from record.
- * @param[out] pCurrentState state retrieved from record.
- *
- * @return index of the packet id in the record if it exists, else the record length.
- */
-static size_t findInRecord( const MQTTPubAckInfo_t * records,
- size_t recordCount,
- uint16_t packetId,
- MQTTQoS_t * pQos,
- MQTTPublishState_t * pCurrentState );
-
-/**
- * @brief Compact records.
- *
- * Records are arranged in the relative order to maintain message ordering.
- * This will lead to fragmentation and this function will help in defragmenting
- * the records array.
- *
- * @param[in] records State record array.
- * @param[in] recordCount Length of record array.
- */
-static void compactRecords( MQTTPubAckInfo_t * records,
- size_t recordCount );
-
-/**
- * @brief Store a new entry in the state record.
- *
- * @param[in] records State record array.
- * @param[in] recordCount Length of record array.
- * @param[in] packetId Packet ID of new entry.
- * @param[in] qos QoS of new entry.
- * @param[in] publishState State of new entry.
- *
- * @return #MQTTSuccess, #MQTTNoMemory, or #MQTTStateCollision.
- */
-static MQTTStatus_t addRecord( MQTTPubAckInfo_t * records,
- size_t recordCount,
- uint16_t packetId,
- MQTTQoS_t qos,
- MQTTPublishState_t publishState );
-
-/**
- * @brief Update and possibly delete an entry in the state record.
- *
- * @param[in] records State record array.
- * @param[in] recordIndex index of record to update.
- * @param[in] newState New state to update.
- * @param[in] shouldDelete Whether an existing entry should be deleted.
- */
-static void updateRecord( MQTTPubAckInfo_t * records,
- size_t recordIndex,
- MQTTPublishState_t newState,
- bool shouldDelete );
-
-/**
- * @brief Get the packet ID and index of an outgoing publish in specified
- * states.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in] searchStates The states to search for in 2-byte bit map.
- * @param[in,out] pCursor Index at which to start searching.
- *
- * @return Packet ID of the outgoing publish.
- */
-static uint16_t stateSelect( const MQTTContext_t * pMqttContext,
- uint16_t searchStates,
- MQTTStateCursor_t * pCursor );
-
-/**
- * @brief Update the state records for an ACK after state transition
- * validations.
- *
- * @param[in] records State records pointer.
- * @param[in] maxRecordCount The maximum number of records.
- * @param[in] recordIndex Index at which the record is stored.
- * @param[in] packetId Packet id of the packet.
- * @param[in] currentState Current state of the publish record.
- * @param[in] newState New state of the publish.
- *
- * @return #MQTTIllegalState, or #MQTTSuccess.
- */
-static MQTTStatus_t updateStateAck( MQTTPubAckInfo_t * records,
- size_t maxRecordCount,
- size_t recordIndex,
- uint16_t packetId,
- MQTTPublishState_t currentState,
- MQTTPublishState_t newState );
-
-/**
- * @brief Update the state record for a PUBLISH packet after validating
- * the state transitions.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in] recordIndex Index in state records at which publish record exists.
- * @param[in] packetId ID of the PUBLISH packet.
- * @param[in] opType Send or Receive.
- * @param[in] qos 0, 1, or 2.
- * @param[in] currentState Current state of the publish record.
- * @param[in] newState New state of the publish record.
- *
- * @return #MQTTIllegalState, #MQTTStateCollision or #MQTTSuccess.
- */
-static MQTTStatus_t updateStatePublish( const MQTTContext_t * pMqttContext,
- size_t recordIndex,
- uint16_t packetId,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos,
- MQTTPublishState_t currentState,
- MQTTPublishState_t newState );
-
-/*-----------------------------------------------------------*/
-
-static bool validateTransitionPublish( MQTTPublishState_t currentState,
- MQTTPublishState_t newState,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos )
-{
- bool isValid = false;
-
- switch( currentState )
- {
- case MQTTStateNull:
-
- /* Transitions from null occur when storing a new entry into the record. */
- if( opType == MQTT_RECEIVE )
- {
- isValid = ( newState == MQTTPubAckSend ) || ( newState == MQTTPubRecSend );
- }
-
- break;
-
- case MQTTPublishSend:
-
- /* Outgoing publish. All such publishes start in this state due to
- * the reserve operation. */
- switch( qos )
- {
- case MQTTQoS1:
- isValid = newState == MQTTPubAckPending;
- break;
-
- case MQTTQoS2:
- isValid = newState == MQTTPubRecPending;
- break;
-
- case MQTTQoS0:
- default:
- /* QoS 0 is checked before calling this function. */
- break;
- }
-
- break;
-
- /* Below cases are for validating the resends of publish when a session is
- * reestablished. */
- case MQTTPubAckPending:
-
- /* When a session is reestablished, outgoing QoS1 publishes in state
- * #MQTTPubAckPending can be resent. The state remains the same. */
- isValid = newState == MQTTPubAckPending;
-
- break;
-
- case MQTTPubRecPending:
-
- /* When a session is reestablished, outgoing QoS2 publishes in state
- * #MQTTPubRecPending can be resent. The state remains the same. */
- isValid = newState == MQTTPubRecPending;
-
- break;
-
- case MQTTPubAckSend:
- case MQTTPubCompPending:
- case MQTTPubCompSend:
- case MQTTPubRecSend:
- case MQTTPubRelPending:
- case MQTTPubRelSend:
- case MQTTPublishDone:
- default:
- /* For a PUBLISH, we should not start from any other state. */
- break;
- }
-
- return isValid;
-}
-
-/*-----------------------------------------------------------*/
-
-static bool validateTransitionAck( MQTTPublishState_t currentState,
- MQTTPublishState_t newState )
-{
- bool isValid = false;
-
- switch( currentState )
- {
- case MQTTPubAckSend:
- /* Incoming publish, QoS 1. */
- case MQTTPubAckPending:
- /* Outgoing publish, QoS 1. */
- isValid = newState == MQTTPublishDone;
- break;
-
- case MQTTPubRecSend:
- /* Incoming publish, QoS 2. */
- isValid = newState == MQTTPubRelPending;
- break;
-
- case MQTTPubRelPending:
-
- /* Incoming publish, QoS 2.
- * There are 2 valid transitions possible.
- * 1. MQTTPubRelPending -> MQTTPubCompSend : A PUBREL ack is received
- * when publish record state is MQTTPubRelPending. This is the
- * normal state transition without any connection interruptions.
- * 2. MQTTPubRelPending -> MQTTPubRelPending : Receiving a duplicate
- * QoS2 publish can result in a transition to the same state.
- * This can happen in the below state transition.
- * 1. Incoming publish received.
- * 2. PUBREC ack sent and state is now MQTTPubRelPending.
- * 3. TCP connection failure and broker didn't receive the PUBREC.
- * 4. Reestablished MQTT session.
- * 5. MQTT broker resent the un-acked publish.
- * 6. Publish is received when publish record state is in
- * MQTTPubRelPending.
- * 7. Sending out a PUBREC will result in this transition
- * to the same state. */
- isValid = ( newState == MQTTPubCompSend ) ||
- ( newState == MQTTPubRelPending );
- break;
-
- case MQTTPubCompSend:
-
- /* Incoming publish, QoS 2.
- * There are 2 valid transitions possible.
- * 1. MQTTPubCompSend -> MQTTPublishDone : A PUBCOMP ack is sent
- * after receiving a PUBREL from broker. This is the
- * normal state transition without any connection interruptions.
- * 2. MQTTPubCompSend -> MQTTPubCompSend : Receiving a duplicate PUBREL
- * can result in a transition to the same state.
- * This can happen in the below state transition.
- * 1. A TCP connection failure happened before sending a PUBCOMP
- * for an incoming PUBREL.
- * 2. Reestablished an MQTT session.
- * 3. MQTT broker resent the un-acked PUBREL.
- * 4. Receiving the PUBREL again will result in this transition
- * to the same state. */
- isValid = ( newState == MQTTPublishDone ) ||
- ( newState == MQTTPubCompSend );
- break;
-
- case MQTTPubRecPending:
- /* Outgoing publish, Qos 2. */
- isValid = newState == MQTTPubRelSend;
- break;
-
- case MQTTPubRelSend:
- /* Outgoing publish, Qos 2. */
- isValid = newState == MQTTPubCompPending;
- break;
-
- case MQTTPubCompPending:
-
- /* Outgoing publish, Qos 2.
- * There are 2 valid transitions possible.
- * 1. MQTTPubCompPending -> MQTTPublishDone : A PUBCOMP is received.
- * This marks the complete state transition for the publish packet.
- * This is the normal state transition without any connection
- * interruptions.
- * 2. MQTTPubCompPending -> MQTTPubCompPending : Resending a PUBREL for
- * packets in state #MQTTPubCompPending can result in this
- * transition to the same state.
- * This can happen in the below state transition.
- * 1. A TCP connection failure happened before receiving a PUBCOMP
- * for an outgoing PUBREL.
- * 2. An MQTT session is reestablished.
- * 3. Resending the un-acked PUBREL results in this transition
- * to the same state. */
- isValid = ( newState == MQTTPublishDone ) ||
- ( newState == MQTTPubCompPending );
- break;
-
- case MQTTPublishDone:
- /* Done state should transition to invalid since it will be removed from the record. */
- case MQTTPublishSend:
- /* If an ack was sent/received we shouldn't have been in this state. */
- case MQTTStateNull:
- /* If an ack was sent/received the record should exist. */
- default:
- /* Invalid. */
- break;
- }
-
- return isValid;
-}
-
-/*-----------------------------------------------------------*/
-
-static bool isPublishOutgoing( MQTTPubAckType_t packetType,
- MQTTStateOperation_t opType )
-{
- bool isOutgoing = false;
-
- switch( packetType )
- {
- case MQTTPuback:
- case MQTTPubrec:
- case MQTTPubcomp:
- isOutgoing = opType == MQTT_RECEIVE;
- break;
-
- case MQTTPubrel:
- isOutgoing = opType == MQTT_SEND;
- break;
-
- default:
- /* No other ack type. */
- break;
- }
-
- return isOutgoing;
-}
-
-/*-----------------------------------------------------------*/
-
-static size_t findInRecord( const MQTTPubAckInfo_t * records,
- size_t recordCount,
- uint16_t packetId,
- MQTTQoS_t * pQos,
- MQTTPublishState_t * pCurrentState )
-{
- size_t index = 0;
-
- assert( packetId != MQTT_PACKET_ID_INVALID );
-
- *pCurrentState = MQTTStateNull;
-
- for( index = 0; index < recordCount; index++ )
- {
- if( records[ index ].packetId == packetId )
- {
- *pQos = records[ index ].qos;
- *pCurrentState = records[ index ].publishState;
- break;
- }
- }
-
- if( index == recordCount )
- {
- index = MQTT_INVALID_STATE_COUNT;
- }
-
- return index;
-}
-
-/*-----------------------------------------------------------*/
-
-static void compactRecords( MQTTPubAckInfo_t * records,
- size_t recordCount )
-{
- size_t index = 0;
- size_t emptyIndex = MQTT_INVALID_STATE_COUNT;
-
- assert( records != NULL );
-
- /* Find the empty spots and fill those with non empty values. */
- for( ; index < recordCount; index++ )
- {
- /* Find the first empty spot. */
- if( records[ index ].packetId == MQTT_PACKET_ID_INVALID )
- {
- if( emptyIndex == MQTT_INVALID_STATE_COUNT )
- {
- emptyIndex = index;
- }
- }
- else
- {
- if( emptyIndex != MQTT_INVALID_STATE_COUNT )
- {
- /* Copy over the contents at non empty index to empty index. */
- records[ emptyIndex ].packetId = records[ index ].packetId;
- records[ emptyIndex ].qos = records[ index ].qos;
- records[ emptyIndex ].publishState = records[ index ].publishState;
-
- /* Mark the record at current non empty index as invalid. */
- records[ index ].packetId = MQTT_PACKET_ID_INVALID;
- records[ index ].qos = MQTTQoS0;
- records[ index ].publishState = MQTTStateNull;
-
- /* Advance the emptyIndex. */
- emptyIndex++;
- }
- }
- }
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t addRecord( MQTTPubAckInfo_t * records,
- size_t recordCount,
- uint16_t packetId,
- MQTTQoS_t qos,
- MQTTPublishState_t publishState )
-{
- MQTTStatus_t status = MQTTNoMemory;
- int32_t index = 0;
- size_t availableIndex = recordCount;
- bool validEntryFound = false;
-
- assert( packetId != MQTT_PACKET_ID_INVALID );
- assert( qos != MQTTQoS0 );
-
- /* Check if we have to compact the records. This is known by checking if
- * the last spot in the array is filled. */
- if( records[ recordCount - 1U ].packetId != MQTT_PACKET_ID_INVALID )
- {
- compactRecords( records, recordCount );
- }
-
- /* Start from end so first available index will be populated.
- * Available index is always found after the last element in the records.
- * This is to make sure the relative order of the records in order to meet
- * the message ordering requirement of MQTT spec 3.1.1. */
- for( index = ( ( int32_t ) recordCount - 1 ); index >= 0; index-- )
- {
- /* Available index is only found after packet at the highest index. */
- if( records[ index ].packetId == MQTT_PACKET_ID_INVALID )
- {
- if( validEntryFound == false )
- {
- availableIndex = ( size_t ) index;
- }
- }
- else
- {
- /* A non-empty spot found in the records. */
- validEntryFound = true;
-
- if( records[ index ].packetId == packetId )
- {
- /* Collision. */
- LogError( ( "Collision when adding PacketID=%u at index=%d.",
- ( unsigned int ) packetId,
- ( int ) index ) );
-
- status = MQTTStateCollision;
- availableIndex = recordCount;
- break;
- }
- }
- }
-
- if( availableIndex < recordCount )
- {
- records[ availableIndex ].packetId = packetId;
- records[ availableIndex ].qos = qos;
- records[ availableIndex ].publishState = publishState;
- status = MQTTSuccess;
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static void updateRecord( MQTTPubAckInfo_t * records,
- size_t recordIndex,
- MQTTPublishState_t newState,
- bool shouldDelete )
-{
- assert( records != NULL );
-
- if( shouldDelete == true )
- {
- /* Mark the record as invalid. */
- records[ recordIndex ].packetId = MQTT_PACKET_ID_INVALID;
- records[ recordIndex ].qos = MQTTQoS0;
- records[ recordIndex ].publishState = MQTTStateNull;
- }
- else
- {
- records[ recordIndex ].publishState = newState;
- }
-}
-
-/*-----------------------------------------------------------*/
-
-static uint16_t stateSelect( const MQTTContext_t * pMqttContext,
- uint16_t searchStates,
- MQTTStateCursor_t * pCursor )
-{
- uint16_t packetId = MQTT_PACKET_ID_INVALID;
- uint16_t outgoingStates = 0U;
- const MQTTPubAckInfo_t * records = NULL;
- size_t maxCount;
- bool stateCheck = false;
-
- assert( pMqttContext != NULL );
- assert( searchStates != 0U );
- assert( pCursor != NULL );
-
- /* Create a bit map with all the outgoing publish states. */
- UINT16_SET_BIT( outgoingStates, MQTTPublishSend );
- UINT16_SET_BIT( outgoingStates, MQTTPubAckPending );
- UINT16_SET_BIT( outgoingStates, MQTTPubRecPending );
- UINT16_SET_BIT( outgoingStates, MQTTPubRelSend );
- UINT16_SET_BIT( outgoingStates, MQTTPubCompPending );
-
- /* Only outgoing publish records need to be searched. */
- assert( ( outgoingStates & searchStates ) > 0U );
- assert( ( ~outgoingStates & searchStates ) == 0U );
-
- records = pMqttContext->outgoingPublishRecords;
- maxCount = pMqttContext->outgoingPublishRecordMaxCount;
-
- while( *pCursor < maxCount )
- {
- /* Check if any of the search states are present. */
- stateCheck = UINT16_CHECK_BIT( searchStates, records[ *pCursor ].publishState );
-
- if( stateCheck == true )
- {
- packetId = records[ *pCursor ].packetId;
- ( *pCursor )++;
- break;
- }
-
- ( *pCursor )++;
- }
-
- return packetId;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTPublishState_t MQTT_CalculateStateAck( MQTTPubAckType_t packetType,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos )
-{
- MQTTPublishState_t calculatedState = MQTTStateNull;
- /* There are more QoS2 cases than QoS1, so initialize to that. */
- bool qosValid = qos == MQTTQoS2;
-
- switch( packetType )
- {
- case MQTTPuback:
- qosValid = qos == MQTTQoS1;
- calculatedState = MQTTPublishDone;
- break;
-
- case MQTTPubrec:
-
- /* Incoming publish: send PUBREC, PUBREL pending.
- * Outgoing publish: receive PUBREC, send PUBREL. */
- calculatedState = ( opType == MQTT_SEND ) ? MQTTPubRelPending : MQTTPubRelSend;
- break;
-
- case MQTTPubrel:
-
- /* Incoming publish: receive PUBREL, send PUBCOMP.
- * Outgoing publish: send PUBREL, PUBCOMP pending. */
- calculatedState = ( opType == MQTT_SEND ) ? MQTTPubCompPending : MQTTPubCompSend;
- break;
-
- case MQTTPubcomp:
- calculatedState = MQTTPublishDone;
- break;
-
- default:
- /* No other ack type. */
- break;
- }
-
- /* Sanity check, make sure ack and QoS agree. */
- if( qosValid == false )
- {
- calculatedState = MQTTStateNull;
- }
-
- return calculatedState;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t updateStateAck( MQTTPubAckInfo_t * records,
- size_t maxRecordCount,
- size_t recordIndex,
- uint16_t packetId,
- MQTTPublishState_t currentState,
- MQTTPublishState_t newState )
-{
- MQTTStatus_t status = MQTTIllegalState;
- bool shouldDeleteRecord = false;
- bool isTransitionValid = false;
-
- assert( records != NULL );
-
- /* Record to be deleted if the state transition is completed or if a PUBREC
- * is received for an outgoing QoS2 publish. When a PUBREC is received,
- * record is deleted and added back to the end of the records to maintain
- * ordering for PUBRELs. */
- shouldDeleteRecord = ( newState == MQTTPublishDone ) || ( newState == MQTTPubRelSend );
- isTransitionValid = validateTransitionAck( currentState, newState );
-
- if( isTransitionValid == true )
- {
- status = MQTTSuccess;
-
- /* Update record for acks. When sending or receiving acks for packets that
- * are resent during a session reestablishment, the new state and
- * current state can be the same. No update of record required in that case. */
- if( currentState != newState )
- {
- updateRecord( records,
- recordIndex,
- newState,
- shouldDeleteRecord );
-
- /* For QoS2 messages, in order to preserve the message ordering, when
- * a PUBREC is received for an outgoing publish, the record should be
- * moved to the last. This move will help preserve the order in which
- * a PUBREL needs to be resent in case of a session reestablishment. */
- if( newState == MQTTPubRelSend )
- {
- status = addRecord( records,
- maxRecordCount,
- packetId,
- MQTTQoS2,
- MQTTPubRelSend );
- }
- }
- }
- else
- {
- /* Invalid state transition. */
- LogError( ( "Invalid transition from state %s to state %s.",
- MQTT_State_strerror( currentState ),
- MQTT_State_strerror( newState ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-static MQTTStatus_t updateStatePublish( const MQTTContext_t * pMqttContext,
- size_t recordIndex,
- uint16_t packetId,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos,
- MQTTPublishState_t currentState,
- MQTTPublishState_t newState )
-{
- MQTTStatus_t status = MQTTSuccess;
- bool isTransitionValid = false;
-
- assert( pMqttContext != NULL );
- assert( packetId != MQTT_PACKET_ID_INVALID );
- assert( qos != MQTTQoS0 );
-
- /* This will always succeed for an incoming publish. This is due to the fact
- * that the passed in currentState must be MQTTStateNull, since
- * #MQTT_UpdateStatePublish does not perform a lookup for receives. */
- isTransitionValid = validateTransitionPublish( currentState, newState, opType, qos );
-
- if( isTransitionValid == true )
- {
- /* addRecord will check for collisions. */
- if( opType == MQTT_RECEIVE )
- {
- status = addRecord( pMqttContext->incomingPublishRecords,
- pMqttContext->incomingPublishRecordMaxCount,
- packetId,
- qos,
- newState );
- }
- /* Send operation. */
- else
- {
- /* Skip updating record when publish is resend and no state
- * update is required. */
- if( currentState != newState )
- {
- updateRecord( pMqttContext->outgoingPublishRecords,
- recordIndex,
- newState,
- false );
- }
- }
- }
- else
- {
- status = MQTTIllegalState;
- LogError( ( "Invalid transition from state %s to state %s.",
- MQTT_State_strerror( currentState ),
- MQTT_State_strerror( newState ) ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_ReserveState( const MQTTContext_t * pMqttContext,
- uint16_t packetId,
- MQTTQoS_t qos )
-{
- MQTTStatus_t status = MQTTSuccess;
-
- if( qos == MQTTQoS0 )
- {
- status = MQTTSuccess;
- }
- else if( ( packetId == MQTT_PACKET_ID_INVALID ) || ( pMqttContext == NULL ) )
- {
- status = MQTTBadParameter;
- }
- else
- {
- /* Collisions are detected when adding the record. */
- status = addRecord( pMqttContext->outgoingPublishRecords,
- pMqttContext->outgoingPublishRecordMaxCount,
- packetId,
- qos,
- MQTTPublishSend );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTPublishState_t MQTT_CalculateStatePublish( MQTTStateOperation_t opType,
- MQTTQoS_t qos )
-{
- MQTTPublishState_t calculatedState = MQTTStateNull;
-
- switch( qos )
- {
- case MQTTQoS0:
- calculatedState = MQTTPublishDone;
- break;
-
- case MQTTQoS1:
- calculatedState = ( opType == MQTT_SEND ) ? MQTTPubAckPending : MQTTPubAckSend;
- break;
-
- case MQTTQoS2:
- calculatedState = ( opType == MQTT_SEND ) ? MQTTPubRecPending : MQTTPubRecSend;
- break;
-
- default:
- /* No other QoS values. */
- break;
- }
-
- return calculatedState;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_UpdateStatePublish( const MQTTContext_t * pMqttContext,
- uint16_t packetId,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos,
- MQTTPublishState_t * pNewState )
-{
- MQTTPublishState_t newState = MQTTStateNull;
- MQTTPublishState_t currentState = MQTTStateNull;
- MQTTStatus_t mqttStatus = MQTTSuccess;
- size_t recordIndex = MQTT_INVALID_STATE_COUNT;
- MQTTQoS_t foundQoS = MQTTQoS0;
-
- if( ( pMqttContext == NULL ) || ( pNewState == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pMqttContext=%p, pNewState=%p",
- ( void * ) pMqttContext,
- ( void * ) pNewState ) );
-
- mqttStatus = MQTTBadParameter;
- }
- else if( qos == MQTTQoS0 )
- {
- /* QoS 0 publish. Do nothing. */
- *pNewState = MQTTPublishDone;
- }
- else if( packetId == MQTT_PACKET_ID_INVALID )
- {
- /* Publishes > QoS 0 need a valid packet ID. */
- mqttStatus = MQTTBadParameter;
- }
- else if( opType == MQTT_SEND )
- {
- /* Search record for entry so we can check QoS. */
- recordIndex = findInRecord( pMqttContext->outgoingPublishRecords,
- pMqttContext->outgoingPublishRecordMaxCount,
- packetId,
- &foundQoS,
- ¤tState );
-
- if( ( recordIndex == MQTT_INVALID_STATE_COUNT ) || ( foundQoS != qos ) )
- {
- /* Entry should match with supplied QoS. */
- mqttStatus = MQTTBadParameter;
- }
- }
- else
- {
- /* QoS 1 or 2 receive. Nothing to be done. */
- }
-
- if( ( qos != MQTTQoS0 ) && ( mqttStatus == MQTTSuccess ) )
- {
- newState = MQTT_CalculateStatePublish( opType, qos );
- /* Validate state transition and update state records. */
- mqttStatus = updateStatePublish( pMqttContext,
- recordIndex,
- packetId,
- opType,
- qos,
- currentState,
- newState );
-
- /* Update output parameter on success. */
- if( mqttStatus == MQTTSuccess )
- {
- *pNewState = newState;
- }
- }
-
- return mqttStatus;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_RemoveStateRecord( const MQTTContext_t * pMqttContext,
- uint16_t packetId )
-{
- MQTTStatus_t status = MQTTSuccess;
- MQTTPubAckInfo_t * records;
- size_t recordIndex;
- /* Current state is updated by the findInRecord function. */
- MQTTPublishState_t currentState;
- MQTTQoS_t qos = MQTTQoS0;
-
-
- if( ( pMqttContext == NULL ) || ( ( pMqttContext->outgoingPublishRecords == NULL ) ) )
- {
- status = MQTTBadParameter;
- }
- else
- {
- records = pMqttContext->outgoingPublishRecords;
-
- recordIndex = findInRecord( records,
- pMqttContext->outgoingPublishRecordMaxCount,
- packetId,
- &qos,
- ¤tState );
-
- if( currentState == MQTTStateNull )
- {
- status = MQTTBadParameter;
- }
- else if( ( qos != MQTTQoS1 ) && ( qos != MQTTQoS2 ) )
- {
- status = MQTTBadParameter;
- }
- else
- {
- /* Delete the record. */
- updateRecord( records,
- recordIndex,
- MQTTStateNull,
- true );
- }
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-MQTTStatus_t MQTT_UpdateStateAck( const MQTTContext_t * pMqttContext,
- uint16_t packetId,
- MQTTPubAckType_t packetType,
- MQTTStateOperation_t opType,
- MQTTPublishState_t * pNewState )
-{
- MQTTPublishState_t newState = MQTTStateNull;
- MQTTPublishState_t currentState = MQTTStateNull;
- bool isOutgoingPublish = isPublishOutgoing( packetType, opType );
- MQTTQoS_t qos = MQTTQoS0;
- size_t maxRecordCount = MQTT_INVALID_STATE_COUNT;
- size_t recordIndex = MQTT_INVALID_STATE_COUNT;
-
- MQTTPubAckInfo_t * records = NULL;
- MQTTStatus_t status = MQTTBadResponse;
-
- if( ( pMqttContext == NULL ) || ( pNewState == NULL ) )
- {
- LogError( ( "Argument cannot be NULL: pMqttContext=%p, pNewState=%p.",
- ( void * ) pMqttContext,
- ( void * ) pNewState ) );
- status = MQTTBadParameter;
- }
- else if( packetId == MQTT_PACKET_ID_INVALID )
- {
- LogError( ( "Packet ID must be nonzero." ) );
- status = MQTTBadParameter;
- }
- else if( packetType > MQTTPubcomp )
- {
- LogError( ( "Invalid packet type %u.", ( unsigned int ) packetType ) );
- status = MQTTBadParameter;
- }
- else
- {
- if( isOutgoingPublish == true )
- {
- records = pMqttContext->outgoingPublishRecords;
- maxRecordCount = pMqttContext->outgoingPublishRecordMaxCount;
- }
- else
- {
- records = pMqttContext->incomingPublishRecords;
- maxRecordCount = pMqttContext->incomingPublishRecordMaxCount;
- }
-
- recordIndex = findInRecord( records,
- maxRecordCount,
- packetId,
- &qos,
- ¤tState );
- }
-
- if( recordIndex != MQTT_INVALID_STATE_COUNT )
- {
- newState = MQTT_CalculateStateAck( packetType, opType, qos );
-
- /* Validate state transition and update state record. */
- status = updateStateAck( records,
- maxRecordCount,
- recordIndex,
- packetId,
- currentState,
- newState );
-
- /* Update the output parameter. */
- if( status == MQTTSuccess )
- {
- *pNewState = newState;
- }
- }
- else
- {
- LogError( ( "No matching record found for publish: PacketId=%u.",
- ( unsigned int ) packetId ) );
- }
-
- return status;
-}
-
-/*-----------------------------------------------------------*/
-
-uint16_t MQTT_PubrelToResend( const MQTTContext_t * pMqttContext,
- MQTTStateCursor_t * pCursor,
- MQTTPublishState_t * pState )
-{
- uint16_t packetId = MQTT_PACKET_ID_INVALID;
- uint16_t searchStates = 0U;
-
- /* Validate arguments. */
- if( ( pMqttContext == NULL ) || ( pCursor == NULL ) || ( pState == NULL ) )
- {
- LogError( ( "Arguments cannot be NULL pMqttContext=%p, pCursor=%p"
- " pState=%p.",
- ( void * ) pMqttContext,
- ( void * ) pCursor,
- ( void * ) pState ) );
- }
- else
- {
- /* PUBREL for packets in state #MQTTPubCompPending and #MQTTPubRelSend
- * would need to be resent when a session is reestablished.*/
- UINT16_SET_BIT( searchStates, MQTTPubCompPending );
- UINT16_SET_BIT( searchStates, MQTTPubRelSend );
- packetId = stateSelect( pMqttContext, searchStates, pCursor );
-
- /* The state needs to be in #MQTTPubRelSend for sending PUBREL. */
- if( packetId != MQTT_PACKET_ID_INVALID )
- {
- *pState = MQTTPubRelSend;
- }
- }
-
- return packetId;
-}
-
-/*-----------------------------------------------------------*/
-
-uint16_t MQTT_PublishToResend( const MQTTContext_t * pMqttContext,
- MQTTStateCursor_t * pCursor )
-{
- uint16_t packetId = MQTT_PACKET_ID_INVALID;
- uint16_t searchStates = 0U;
-
- /* Validate arguments. */
- if( ( pMqttContext == NULL ) || ( pCursor == NULL ) )
- {
- LogError( ( "Arguments cannot be NULL pMqttContext=%p, pCursor=%p",
- ( void * ) pMqttContext,
- ( void * ) pCursor ) );
- }
- else
- {
- /* Packets in state #MQTTPublishSend, #MQTTPubAckPending and
- * #MQTTPubRecPending would need to be resent when a session is
- * reestablished. */
- UINT16_SET_BIT( searchStates, MQTTPublishSend );
- UINT16_SET_BIT( searchStates, MQTTPubAckPending );
- UINT16_SET_BIT( searchStates, MQTTPubRecPending );
-
- packetId = stateSelect( pMqttContext, searchStates, pCursor );
- }
-
- return packetId;
-}
-
-/*-----------------------------------------------------------*/
-
-const char * MQTT_State_strerror( MQTTPublishState_t state )
-{
- const char * str = NULL;
-
- switch( state )
- {
- case MQTTStateNull:
- str = "MQTTStateNull";
- break;
-
- case MQTTPublishSend:
- str = "MQTTPublishSend";
- break;
-
- case MQTTPubAckSend:
- str = "MQTTPubAckSend";
- break;
-
- case MQTTPubRecSend:
- str = "MQTTPubRecSend";
- break;
-
- case MQTTPubRelSend:
- str = "MQTTPubRelSend";
- break;
-
- case MQTTPubCompSend:
- str = "MQTTPubCompSend";
- break;
-
- case MQTTPubAckPending:
- str = "MQTTPubAckPending";
- break;
-
- case MQTTPubRecPending:
- str = "MQTTPubRecPending";
- break;
-
- case MQTTPubRelPending:
- str = "MQTTPubRelPending";
- break;
-
- case MQTTPubCompPending:
- str = "MQTTPubCompPending";
- break;
-
- case MQTTPublishDone:
- str = "MQTTPublishDone";
- break;
-
- default:
- /* Invalid state received. */
- str = "Invalid MQTT State";
- break;
- }
-
- return str;
-}
-
-/*-----------------------------------------------------------*/
diff --git a/project/coreMQTT/coreMQTT/core_mqtt_state.h b/project/coreMQTT/coreMQTT/core_mqtt_state.h
deleted file mode 100644
index 0644489..0000000
--- a/project/coreMQTT/coreMQTT/core_mqtt_state.h
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_mqtt_state.h
- * @brief Function to keep state of MQTT PUBLISH packet deliveries.
- */
-#ifndef CORE_MQTT_STATE_H
-#define CORE_MQTT_STATE_H
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-#include "core_mqtt.h"
-
-/**
- * @ingroup mqtt_constants
- * @brief Initializer value for an #MQTTStateCursor_t, indicating a search
- * should start at the beginning of a state record array
- */
-#define MQTT_STATE_CURSOR_INITIALIZER ( ( size_t ) 0 )
-
-/**
- * @ingroup mqtt_basic_types
- * @brief Cursor for iterating through state records.
- */
-typedef size_t MQTTStateCursor_t;
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this section, this enum is private.
- *
- * @brief Value indicating either send or receive.
- */
-typedef enum MQTTStateOperation
-{
- MQTT_SEND,
- MQTT_RECEIVE
-} MQTTStateOperation_t;
-/** @endcond */
-
-/**
- * @fn MQTTStatus_t MQTT_ReserveState( const MQTTContext_t * pMqttContext, uint16_t packetId, MQTTQoS_t qos );
- * @brief Reserve an entry for an outgoing QoS 1 or Qos 2 publish.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in] packetId The ID of the publish packet.
- * @param[in] qos 1 or 2.
- *
- * @return MQTTSuccess, MQTTNoMemory, or MQTTStateCollision.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-MQTTStatus_t MQTT_ReserveState( const MQTTContext_t * pMqttContext,
- uint16_t packetId,
- MQTTQoS_t qos );
-/** @endcond */
-
-/**
- * @fn MQTTPublishState_t MQTT_CalculateStatePublish( MQTTStateOperation_t opType, MQTTQoS_t qos )
- * @brief Calculate the new state for a publish from its qos and operation type.
- *
- * @param[in] opType Send or Receive.
- * @param[in] qos 0, 1, or 2.
- *
- * @return The calculated state.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-MQTTPublishState_t MQTT_CalculateStatePublish( MQTTStateOperation_t opType,
- MQTTQoS_t qos );
-/** @endcond */
-
-/**
- * @fn MQTTStatus_t MQTT_UpdateStatePublish( const MQTTContext_t * pMqttContext, uint16_t packetId, MQTTStateOperation_t opType, MQTTQoS_t qos, MQTTPublishState_t * pNewState );
- * @brief Update the state record for a PUBLISH packet.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in] packetId ID of the PUBLISH packet.
- * @param[in] opType Send or Receive.
- * @param[in] qos 0, 1, or 2.
- * @param[out] pNewState Updated state of the publish.
- *
- * @return #MQTTBadParameter, #MQTTIllegalState, #MQTTStateCollision or
- * #MQTTSuccess.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-MQTTStatus_t MQTT_UpdateStatePublish( const MQTTContext_t * pMqttContext,
- uint16_t packetId,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos,
- MQTTPublishState_t * pNewState );
-/** @endcond */
-
-/**
- * @fn MQTTStatus_t MQTT_RemoveStateRecord( const MQTTContext_t * pMqttContext, uint16_t packetId );
- * @brief Remove the state record for a PUBLISH packet.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in] packetId ID of the PUBLISH packet.
- *
- * @return #MQTTBadParameter or #MQTTSuccess.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-MQTTStatus_t MQTT_RemoveStateRecord( const MQTTContext_t * pMqttContext,
- uint16_t packetId );
-/** @endcond */
-
-/**
- * @fn MQTTPublishState_t MQTT_CalculateStateAck( MQTTPubAckType_t packetType, MQTTStateOperation_t opType, MQTTQoS_t qos );
- * @brief Calculate the state from a PUBACK, PUBREC, PUBREL, or PUBCOMP.
- *
- * @param[in] packetType PUBACK, PUBREC, PUBREL, or PUBCOMP.
- * @param[in] opType Send or Receive.
- * @param[in] qos 1 or 2.
- *
- * @return The calculated state.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-MQTTPublishState_t MQTT_CalculateStateAck( MQTTPubAckType_t packetType,
- MQTTStateOperation_t opType,
- MQTTQoS_t qos );
-/** @endcond */
-
-/**
- * @fn MQTTStatus_t MQTT_UpdateStateAck( const MQTTContext_t * pMqttContext, uint16_t packetId, MQTTPubAckType_t packetType, MQTTStateOperation_t opType, MQTTPublishState_t * pNewState );
- * @brief Update the state record for an ACKed publish.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in] packetId ID of the ack packet.
- * @param[in] packetType PUBACK, PUBREC, PUBREL, or PUBCOMP.
- * @param[in] opType Send or Receive.
- * @param[out] pNewState Updated state of the publish.
- *
- * @return #MQTTBadParameter if an invalid parameter is passed;
- * #MQTTBadResponse if the packet from the network is not found in the records;
- * #MQTTIllegalState if the requested update would result in an illegal transition;
- * #MQTTSuccess otherwise.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-MQTTStatus_t MQTT_UpdateStateAck( const MQTTContext_t * pMqttContext,
- uint16_t packetId,
- MQTTPubAckType_t packetType,
- MQTTStateOperation_t opType,
- MQTTPublishState_t * pNewState );
-/** @endcond */
-
-/**
- * @fn uint16_t MQTT_PubrelToResend( const MQTTContext_t * pMqttContext, MQTTStateCursor_t * pCursor, MQTTPublishState_t * pState );
- * @brief Get the packet ID of next pending PUBREL ack to be resent.
- *
- * This function will need to be called to get the packet for which a PUBREL
- * need to be sent when a session is reestablished. Calling this function
- * repeatedly until packet id is 0 will give all the packets for which
- * a PUBREL need to be resent in the correct order.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in,out] pCursor Index at which to start searching.
- * @param[out] pState State indicating that PUBREL packet need to be sent.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-uint16_t MQTT_PubrelToResend( const MQTTContext_t * pMqttContext,
- MQTTStateCursor_t * pCursor,
- MQTTPublishState_t * pState );
-/** @endcond */
-
-/**
- * @brief Get the packet ID of next pending publish to be resent.
- *
- * This function will need to be called to get the packet for which a publish
- * need to be sent when a session is reestablished. Calling this function
- * repeatedly until packet id is 0 will give all the packets for which
- * a publish need to be resent in the correct order.
- *
- * @param[in] pMqttContext Initialized MQTT context.
- * @param[in,out] pCursor Index at which to start searching.
- *
- * <b>Example</b>
- * @code{c}
- *
- * // For this example assume this function returns an outgoing unacknowledged
- * // QoS 1 or 2 publish from its packet identifier.
- * MQTTPublishInfo_t * getPublish( uint16_t packetID );
- *
- * // Variables used in this example.
- * MQTTStatus_t status;
- * MQTTStateCursor_t cursor = MQTT_STATE_CURSOR_INITIALIZER;
- * bool sessionPresent;
- * uint16_t packetID;
- * MQTTPublishInfo_t * pResendPublish = NULL;
- * MQTTConnectInfo_t connectInfo = { 0 };
- *
- * // This is assumed to have been initialized before the call to MQTT_Connect().
- * MQTTContext_t * pContext;
- *
- * // Set clean session to false to attempt session resumption.
- * connectInfo.cleanSession = false;
- * connectInfo.pClientIdentifier = "someClientID";
- * connectInfo.clientIdentifierLength = strlen( connectInfo.pClientIdentifier );
- * connectInfo.keepAliveSeconds = 60;
- * // Optional connect parameters are not relevant to this example.
- *
- * // Create an MQTT connection. Use 100 milliseconds as a timeout.
- * status = MQTT_Connect( pContext, &connectInfo, NULL, 100, &sessionPresent );
- *
- * if( status == MQTTSuccess )
- * {
- * if( sessionPresent )
- * {
- * // Loop while packet ID is nonzero.
- * while( ( packetID = MQTT_PublishToResend( pContext, &cursor ) ) != 0 )
- * {
- * // Assume this function will succeed.
- * pResendPublish = getPublish( packetID );
- * // Set DUP flag.
- * pResendPublish->dup = true;
- * status = MQTT_Publish( pContext, pResendPublish, packetID );
- *
- * if( status != MQTTSuccess )
- * {
- * // Application can decide how to handle a failure.
- * }
- * }
- * }
- * else
- * {
- * // The broker did not resume a session, so we can clean up the
- * // list of outgoing publishes.
- * }
- * }
- * @endcode
- */
-/* @[declare_mqtt_publishtoresend] */
-uint16_t MQTT_PublishToResend( const MQTTContext_t * pMqttContext,
- MQTTStateCursor_t * pCursor );
-/* @[declare_mqtt_publishtoresend] */
-
-/**
- * @fn const char * MQTT_State_strerror( MQTTPublishState_t state );
- * @brief State to string conversion for state engine.
- *
- * @param[in] state The state to convert to a string.
- *
- * @return The string representation of the state.
- */
-
-/**
- * @cond DOXYGEN_IGNORE
- * Doxygen should ignore this definition, this function is private.
- */
-const char * MQTT_State_strerror( MQTTPublishState_t state );
-/** @endcond */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_MQTT_STATE_H */
diff --git a/project/coreMQTT/coreMQTT/makefile b/project/coreMQTT/coreMQTT/makefile
deleted file mode 100644
index b6ece0e..0000000
--- a/project/coreMQTT/coreMQTT/makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#********************************************************************************
-# Copyright: (C) 2023 LingYun IoT System Studio
-# All rights reserved.
-#
-# Filename: Makefile
-# Description: This file used compile all the source code to static library
-#
-# Version: 1.0.0(11/08/23)
-# Author: Guo Wenxue <guowenxue@gmail.com>
-# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
-#
-#*******************************************************************************
-
-PWD=$(shell pwd )
-
-BUILD_ARCH=$(shell uname -m)
-ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
- CROSS_COMPILE?=arm-linux-gnueabihf-
-endif
-
-LIBNAME=$(shell basename ${PWD} )
-TOPDIR=$(shell dirname ${PWD} )
-CFLAGS+=-D_GNU_SOURCE
-
-all: clean
- @rm -f *.o
- @${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c
- ${CROSS_COMPILE}ar -rcs lib${LIBNAME}.a *.o
-
-clean:
- @rm -f *.o
- @rm -f *.a
-
-distclean:
- @make clean
diff --git a/project/coreMQTT/coreMQTT/transport_interface.h b/project/coreMQTT/coreMQTT/transport_interface.h
deleted file mode 100644
index e86443d..0000000
--- a/project/coreMQTT/coreMQTT/transport_interface.h
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
- * coreMQTT v2.1.1
- * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file transport_interface.h
- * @brief Transport interface definitions to send and receive data over the
- * network.
- */
-#ifndef TRANSPORT_INTERFACE_H_
-#define TRANSPORT_INTERFACE_H_
-
-#include <stdint.h>
-#include <stddef.h>
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/**
- * @transportpage
- * @brief The transport interface definition.
- *
- * @transportsectionoverview
- *
- * The transport interface is a set of APIs that must be implemented using an
- * external transport layer protocol. The transport interface is defined in
- * @ref transport_interface.h. This interface allows protocols like MQTT and
- * HTTP to send and receive data over the transport layer. This
- * interface does not handle connection and disconnection to the server of
- * interest. The connection, disconnection, and other transport settings, like
- * timeout and TLS setup, must be handled in the user application.
- * <br>
- *
- * The functions that must be implemented are:<br>
- * - [Transport Receive](@ref TransportRecv_t)
- * - [Transport Send](@ref TransportSend_t)
- *
- * Each of the functions above take in an opaque context @ref NetworkContext_t.
- * The functions above and the context are also grouped together in the
- * @ref TransportInterface_t structure:<br><br>
- * @snippet this define_transportinterface
- * <br>
- *
- * @transportsectionimplementation
- *
- * The following steps give guidance on implementing the transport interface:
- *
- * -# Implementing @ref NetworkContext_t<br><br>
- * @snippet this define_networkcontext
- * <br>
- * @ref NetworkContext_t is the incomplete type <b>struct NetworkContext</b>.
- * The implemented struct NetworkContext must contain all of the information
- * that is needed to receive and send data with the @ref TransportRecv_t
- * and the @ref TransportSend_t implementations.<br>
- * In the case of TLS over TCP, struct NetworkContext is typically implemented
- * with the TCP socket context and a TLS context.<br><br>
- * <b>Example code:</b>
- * @code{c}
- * struct NetworkContext
- * {
- * struct MyTCPSocketContext tcpSocketContext;
- * struct MyTLSContext tlsContext;
- * };
- * @endcode
- * <br>
- * -# Implementing @ref TransportRecv_t<br><br>
- * @snippet this define_transportrecv
- * <br>
- * This function is expected to populate a buffer, with bytes received from the
- * transport, and return the number of bytes placed in the buffer.
- * In the case of TLS over TCP, @ref TransportRecv_t is typically implemented by
- * calling the TLS layer function to receive data. In case of plaintext TCP
- * without TLS, it is typically implemented by calling the TCP layer receive
- * function. @ref TransportRecv_t may be invoked multiple times by the protocol
- * library, if fewer bytes than were requested to receive are returned.
- * <br><br>
- * <b>Example code:</b>
- * @code{c}
- * int32_t myNetworkRecvImplementation( NetworkContext_t * pNetworkContext,
- * void * pBuffer,
- * size_t bytesToRecv )
- * {
- * int32_t bytesReceived = 0;
- * bool callTlsRecvFunc = true;
- *
- * // For a single byte read request, check if data is available on the network.
- * if( bytesToRecv == 1 )
- * {
- * // If no data is available on the network, do not call TLSRecv
- * // to avoid blocking for socket timeout.
- * if( TLSRecvCount( pNetworkContext->tlsContext ) == 0 )
- * {
- * callTlsRecvFunc = false;
- * }
- * }
- *
- * if( callTlsRecvFunc == true )
- * {
- * bytesReceived = TLSRecv( pNetworkContext->tlsContext,
- * pBuffer,
- * bytesToRecv,
- * MY_SOCKET_TIMEOUT );
- * if( bytesReceived < 0 )
- * {
- * // If the error code represents a timeout, then the return
- * // code should be translated to zero so that the caller
- * // can retry the read operation.
- * if( bytesReceived == MY_SOCKET_ERROR_TIMEOUT )
- * {
- * bytesReceived = 0;
- * }
- * }
- * // Handle other cases.
- * }
- * return bytesReceived;
- * }
- * @endcode
- * <br>
- * -# Implementing @ref TransportSend_t<br><br>
- * @snippet this define_transportsend
- * <br>
- * This function is expected to send the bytes, in the given buffer over the
- * transport, and return the number of bytes sent.
- * In the case of TLS over TCP, @ref TransportSend_t is typically implemented by
- * calling the TLS layer function to send data. In case of plaintext TCP
- * without TLS, it is typically implemented by calling the TCP layer send
- * function. @ref TransportSend_t may be invoked multiple times by the protocol
- * library, if fewer bytes than were requested to send are returned.
- * <br><br>
- * <b>Example code:</b>
- * @code{c}
- * int32_t myNetworkSendImplementation( NetworkContext_t * pNetworkContext,
- * const void * pBuffer,
- * size_t bytesToSend )
- * {
- * int32_t bytesSent = 0;
- * bytesSent = TLSSend( pNetworkContext->tlsContext,
- * pBuffer,
- * bytesToSend,
- * MY_SOCKET_TIMEOUT );
- *
- * // If underlying TCP buffer is full, set the return value to zero
- * // so that caller can retry the send operation.
- * if( bytesSent == MY_SOCKET_ERROR_BUFFER_FULL )
- * {
- * bytesSent = 0;
- * }
- * else if( bytesSent < 0 )
- * {
- * // Handle socket error.
- * }
- * // Handle other cases.
- *
- * return bytesSent;
- * }
- * @endcode
- */
-
-/**
- * @transportstruct
- * @typedef NetworkContext_t
- * @brief The NetworkContext is an incomplete type. An implementation of this
- * interface must define struct NetworkContext for the system requirements.
- * This context is passed into the network interface functions.
- */
-/* @[define_networkcontext] */
-struct NetworkContext;
-typedef struct NetworkContext NetworkContext_t;
-/* @[define_networkcontext] */
-
-/**
- * @transportcallback
- * @brief Transport interface for receiving data on the network.
- *
- * @note It is RECOMMENDED that the transport receive implementation
- * does NOT block when requested to read a single byte. A single byte
- * read request can be made by the caller to check whether there is a
- * new frame available on the network for reading.
- * However, the receive implementation MAY block for a timeout period when
- * it is requested to read more than 1 byte. This is because once the caller
- * is aware that a new frame is available to read on the network, then
- * the likelihood of reading more than one byte over the network becomes high.
- *
- * @param[in] pNetworkContext Implementation-defined network context.
- * @param[in] pBuffer Buffer to receive the data into.
- * @param[in] bytesToRecv Number of bytes requested from the network.
- *
- * @return The number of bytes received or a negative value to indicate
- * error.
- *
- * @note If no data is available on the network to read and no error
- * has occurred, zero MUST be the return value. A zero return value
- * SHOULD represent that the read operation can be retried by calling
- * the API function. Zero MUST NOT be returned if a network disconnection
- * has occurred.
- */
-/* @[define_transportrecv] */
-typedef int32_t ( * TransportRecv_t )( NetworkContext_t * pNetworkContext,
- void * pBuffer,
- size_t bytesToRecv );
-/* @[define_transportrecv] */
-
-/**
- * @transportcallback
- * @brief Transport interface for sending data over the network.
- *
- * @param[in] pNetworkContext Implementation-defined network context.
- * @param[in] pBuffer Buffer containing the bytes to send over the network stack.
- * @param[in] bytesToSend Number of bytes to send over the network.
- *
- * @return The number of bytes sent or a negative value to indicate error.
- *
- * @note If no data is transmitted over the network due to a full TX buffer and
- * no network error has occurred, this MUST return zero as the return value.
- * A zero return value SHOULD represent that the send operation can be retried
- * by calling the API function. Zero MUST NOT be returned if a network disconnection
- * has occurred.
- */
-/* @[define_transportsend] */
-typedef int32_t ( * TransportSend_t )( NetworkContext_t * pNetworkContext,
- const void * pBuffer,
- size_t bytesToSend );
-/* @[define_transportsend] */
-
-/**
- * @brief Transport vector structure for sending multiple messages.
- */
-typedef struct TransportOutVector
-{
- /**
- * @brief Base address of data.
- */
- const void * iov_base;
-
- /**
- * @brief Length of data in buffer.
- */
- size_t iov_len;
-} TransportOutVector_t;
-
-/**
- * @transportcallback
- * @brief Transport interface function for "vectored" / scatter-gather based
- * writes. This function is expected to iterate over the list of vectors pIoVec
- * having ioVecCount entries containing portions of one MQTT message at a maximum.
- * If the proper functionality is available, then the data in the list should be
- * copied to the underlying TCP buffer before flushing the buffer. Implementing it
- * in this fashion will lead to sending of fewer TCP packets for all the values
- * in the list.
- *
- * @note If the proper write functionality is not present for a given device/IP-stack,
- * then there is no strict requirement to implement write. Only the send and recv
- * interfaces must be defined for the application to work properly.
- *
- * @param[in] pNetworkContext Implementation-defined network context.
- * @param[in] pIoVec An array of TransportIoVector_t structs.
- * @param[in] ioVecCount Number of TransportIoVector_t in pIoVec.
- *
- * @return The number of bytes written or a negative value to indicate error.
- *
- * @note If no data is written to the buffer due to the buffer being full this MUST
- * return zero as the return value.
- * A zero return value SHOULD represent that the write operation can be retried
- * by calling the API function. Zero MUST NOT be returned if a network disconnection
- * has occurred.
- */
-/* @[define_transportwritev] */
-typedef int32_t ( * TransportWritev_t )( NetworkContext_t * pNetworkContext,
- TransportOutVector_t * pIoVec,
- size_t ioVecCount );
-/* @[define_transportwritev] */
-
-/**
- * @transportstruct
- * @brief The transport layer interface.
- */
-/* @[define_transportinterface] */
-typedef struct TransportInterface
-{
- TransportRecv_t recv; /**< Transport receive function pointer. */
- TransportSend_t send; /**< Transport send function pointer. */
- TransportWritev_t writev; /**< Transport writev function pointer. */
- NetworkContext_t * pNetworkContext; /**< Implementation-defined network context. */
-} TransportInterface_t;
-/* @[define_transportinterface] */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef TRANSPORT_INTERFACE_H_ */
diff --git a/project/coreMQTT/coreSNTP/README.md b/project/coreMQTT/coreSNTP/README.md
deleted file mode 100644
index 597e271..0000000
--- a/project/coreMQTT/coreSNTP/README.md
+++ /dev/null
@@ -1,28 +0,0 @@
-## coreSNTP Library
-
-This repository contains the coreSNTP library, a client library to use Simple Network Time Protocol (SNTP) to synchronize device clocks with internet time. This library implements the SNTPv4 specification defined in [RFC 4330](https://tools.ietf.org/html/rfc4330).
-
-An SNTP client can request time from both NTP and SNTP servers. According to the SNTPv4 specification, "_To an NTP or SNTP server, NTP and SNTP clients are indistinguishable; to an NTP or SNTP client, NTP and SNTP servers are indistinguishable._", thereby, allowing SNTP clients to request time from NTP servers.
-
-**coreSNTP v1.2.0 [source code](https://github.com/FreeRTOS/coreSNTP/tree/v1.2.0/source) is part of the [FreeRTOS 202210.00 LTS](https://github.com/FreeRTOS/FreeRTOS-LTS/tree/202210.00-LTS) release.**
-
-## Documentation
-
-The API reference documentation for the coreSNTP library version released in [FreeRTOS/FreeRTOS](https://github.com/FreeRTOS/FreeRTOS) can be viewed from the [freertos.org website](https://freertos.org/coresntp/index.html).
-
-## Cloning this repository
-This repo uses [Git Submodules](https://git-scm.com/book/en/v2/Git-Tools-Submodules) to bring in dependent components.
-
-To clone using HTTPS:
-```
-git clone https://github.com/FreeRTOS/coreSNTP.git --recurse-submodules
-```
-Using SSH:
-```
-git clone git@github.com:FreeRTOS/coreSNTP.git --recurse-submodules
-```
-
-If you have downloaded the repo without using the `--recurse-submodules` argument, you need to run:
-```
-git submodule update --init --recursive
-```
diff --git a/project/coreMQTT/coreSNTP/core_sntp_client.c b/project/coreMQTT/coreSNTP/core_sntp_client.c
deleted file mode 100644
index 6b4d8d9..0000000
--- a/project/coreMQTT/coreSNTP/core_sntp_client.c
+++ /dev/null
@@ -1,959 +0,0 @@
-/*
- * coreSNTP v1.2.0
- * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_sntp_client.c
- * @brief Implementation of the client API of the coreSNTP library.
- */
-
-/* Standard includes. */
-#include <assert.h>
-#include <string.h>
-
-/* SNTP client library API include. */
-#include "core_sntp_client.h"
-
-#include "core_sntp_config_defaults.h"
-
-/**
- * @brief Utility to convert fractions part of SNTP timestamp to milliseconds.
- *
- * @param[in] fractions The fractions value in an SNTP timestamp.
- */
-#define FRACTIONS_TO_MS( fractions ) \
- ( fractions / ( SNTP_FRACTION_VALUE_PER_MICROSECOND * 1000U ) )
-
-SntpStatus_t Sntp_Init( SntpContext_t * pContext,
- const SntpServerInfo_t * pTimeServers,
- size_t numOfServers,
- uint32_t serverResponseTimeoutMs,
- uint8_t * pNetworkBuffer,
- size_t bufferSize,
- SntpResolveDns_t resolveDnsFunc,
- SntpGetTime_t getSystemTimeFunc,
- SntpSetTime_t setSystemTimeFunc,
- const UdpTransportInterface_t * pTransportIntf,
- const SntpAuthenticationInterface_t * pAuthIntf )
-{
- SntpStatus_t status = SntpSuccess;
-
- /* Validate pointer parameters are not NULL. */
- if( ( pContext == NULL ) || ( pTimeServers == NULL ) ||
- ( pNetworkBuffer == NULL ) || ( resolveDnsFunc == NULL ) ||
- ( getSystemTimeFunc == NULL ) || ( setSystemTimeFunc == NULL ) ||
- ( pTransportIntf == NULL ) )
- {
- LogError( ( "Invalid parameter: Pointer parameters (except pAuthIntf) cannot be NULL" ) );
-
- status = SntpErrorBadParameter;
- }
- /* Validate the length of the servers list.*/
- else if( numOfServers == 0U )
- {
- LogError( ( "Invalid parameter: Size of server list cannot be zero" ) );
- status = SntpErrorBadParameter;
- }
- /* Validate that the UDP transport interface functions are valid. */
- else if( ( pTransportIntf->recvFrom == NULL ) || ( pTransportIntf->sendTo == NULL ) )
- {
- LogError( ( "Invalid parameter: Function members of UDP transport interface cannot be NULL" ) );
- status = SntpErrorBadParameter;
- }
-
- /* If an authentication interface is provided, validate that its function pointer
- * members are valid. */
- else if( ( pAuthIntf != NULL ) &&
- ( ( pAuthIntf->generateClientAuth == NULL ) ||
- ( pAuthIntf->validateServerAuth == NULL ) ) )
- {
- LogError( ( "Invalid parameter: Function members of authentication interface cannot be NULL" ) );
- status = SntpErrorBadParameter;
- }
- else if( bufferSize < SNTP_PACKET_BASE_SIZE )
- {
- LogError( ( "Cannot initialize context: Passed network buffer size is less than %u bytes: "
- "bufferSize=%lu", SNTP_PACKET_BASE_SIZE, ( unsigned long ) bufferSize ) );
- status = SntpErrorBufferTooSmall;
- }
- else
- {
- /* Reset the context memory to zero. */
- ( void ) memset( pContext, 0, sizeof( SntpContext_t ) );
-
- /* Set the members of the context with passed parameters. */
- pContext->pTimeServers = pTimeServers;
- pContext->numOfServers = numOfServers;
-
- pContext->responseTimeoutMs = serverResponseTimeoutMs;
-
- pContext->pNetworkBuffer = pNetworkBuffer;
- pContext->bufferSize = bufferSize;
-
- pContext->resolveDnsFunc = resolveDnsFunc;
- pContext->getTimeFunc = getSystemTimeFunc;
- pContext->setTimeFunc = setSystemTimeFunc;
-
- /* Copy contents of UDP transport interface to context. */
- ( void ) memcpy( &pContext->networkIntf, pTransportIntf, sizeof( UdpTransportInterface_t ) );
-
- /* If authentication interface has been passed, copy its contents to the context. */
- if( pAuthIntf != NULL )
- {
- ( void ) memcpy( &pContext->authIntf, pAuthIntf, sizeof( SntpAuthenticationInterface_t ) );
- }
-
- /* Initialize the packet size member to the standard minimum SNTP packet size.*/
- pContext->sntpPacketSize = SNTP_PACKET_BASE_SIZE;
- }
-
- return status;
-}
-
-/**
- * @brief Utility to calculate the difference in milliseconds between 2
- * SNTP timestamps.
- *
- * @param[in] pCurrentTime The more recent timestamp.
- * @param[in] pOlderTime The older timestamp.
- *
- * @note This functions supports the edge case of SNTP timestamp overflow
- * when @p pCurrentTime represents time in NTP era 1 (i.e. time since 7 Feb 2036)
- * and the @p OlderTime represents time in NTP era 0 (i.e. time since 1st Jan 1900).
- *
- * @return Returns the calculated time duration between the two timestamps.
- *
- * @note This function returns the calculated time difference as unsigned 64 bit
- * to avoid integer overflow when converting time difference between the seconds part
- * of the timestamps, which are 32 bits wide, to milliseconds.
- */
-static uint64_t calculateElapsedTimeMs( const SntpTimestamp_t * pCurrentTime,
- const SntpTimestamp_t * pOlderTime )
-{
- uint64_t timeDiffMs = 0UL;
- uint32_t timeDiffSec = 0U;
-
- assert( pCurrentTime != NULL );
- assert( pOlderTime != NULL );
-
- /* Detect if SNTP time has overflown between the 2 timestamps. */
- if( pCurrentTime->seconds < pOlderTime->seconds )
- {
- /* Handle the SNTP time overflow by calculating the actual time
- * duration from pOlderTime, that exists in NTP era 0, to pCurrentTime,
- * that exists in NTP era 1. */
- timeDiffSec = ( UINT32_MAX - pOlderTime->seconds ) + /* Time in NTP era 0. */
- 1U + /* Epoch time in NTP era 1, i.e. 7 Feb 2036 6h:14m:28s. */
- pCurrentTime->seconds; /* Time in NTP era 1. */
-
- timeDiffMs = ( uint64_t ) timeDiffSec * 1000UL;
- }
- else
- {
- timeDiffSec = ( pCurrentTime->seconds - pOlderTime->seconds );
- timeDiffMs = ( uint64_t ) timeDiffSec * 1000UL;
- }
-
- if( pCurrentTime->fractions > pOlderTime->fractions )
- {
- timeDiffMs += ( ( uint64_t ) pCurrentTime->fractions - ( uint64_t ) pOlderTime->fractions ) /
- ( SNTP_FRACTION_VALUE_PER_MICROSECOND * 1000UL );
- }
- else
- {
- timeDiffMs -= ( ( uint64_t ) pOlderTime->fractions - ( uint64_t ) pCurrentTime->fractions ) /
- ( SNTP_FRACTION_VALUE_PER_MICROSECOND * 1000UL );
- }
-
- return timeDiffMs;
-}
-
-/**
- * @brief Validates the content of the SNTP context passed to the APIs to
- * check whether it represents an initialized context.
- *
- * @param[in] pContext The SNTP context to validate.
- *
- * @return Returns one of the following:
- * - #SntpSuccess if the context is verified to be initialized.
- * - #SntpErrorBadParameter if the context is NULL.
- * - #SntpErrorContextNotInitialized if the context is validated to be initialized.
- */
-static SntpStatus_t validateContext( const SntpContext_t * pContext )
-{
- SntpStatus_t status = SntpSuccess;
-
- /* Check if the context parameter is invalid. */
- if( pContext == NULL )
- {
- status = SntpErrorBadParameter;
- LogError( ( "Invalid context parameter: Context is NULL" ) );
- }
-
- /* Validate pointer parameters are not NULL. */
- else if( ( pContext->pTimeServers == NULL ) || ( pContext->pNetworkBuffer == NULL ) ||
- ( pContext->resolveDnsFunc == NULL ) ||
- ( pContext->getTimeFunc == NULL ) || ( pContext->setTimeFunc == NULL ) )
- {
- status = SntpErrorContextNotInitialized;
- }
-
- /* Validate the size of the configured servers list, network buffer size and the state
- * variable for the SNTP packet size.*/
- else if( ( pContext->numOfServers == 0U ) || ( pContext->bufferSize < SNTP_PACKET_BASE_SIZE ) ||
- ( pContext->sntpPacketSize < SNTP_PACKET_BASE_SIZE ) )
- {
- status = SntpErrorContextNotInitialized;
- }
- /* Validate that the UDP transport interface functions are valid. */
- else if( ( pContext->networkIntf.recvFrom == NULL ) || ( pContext->networkIntf.sendTo == NULL ) )
- {
- status = SntpErrorContextNotInitialized;
- }
-
- /* If an authentication interface is provided, validate that both its function pointer
- * members are valid. */
- else if( ( ( pContext->authIntf.generateClientAuth != NULL ) && ( pContext->authIntf.validateServerAuth == NULL ) ) ||
- ( ( pContext->authIntf.generateClientAuth == NULL ) && ( pContext->authIntf.validateServerAuth != NULL ) ) )
- {
- status = SntpErrorContextNotInitialized;
- }
- else
- {
- status = SntpSuccess;
- }
-
- if( status == SntpErrorContextNotInitialized )
- {
- LogError( ( "Invalid context parameter: Context is not initialized with Sntp_Init" ) );
- }
-
- return status;
-}
-
-/**
- * @brief Sends SNTP request packet to the passed server over the network
- * using transport interface's send function.
- *
- * @note For the case of zero byte transmissions over the network, this function
- * repeatedly retries the send operation by calling the transport interface
- * until either:
- * 1. The requested number of bytes @p packetSize have been sent.
- * OR
- * 2. There is an error in sending data over the network.
- *
- * @note This function treats partial data transmissions as error as UDP
- * transport protocol does not support partial sends.
- *
- * @param[in] pNetworkIntf The UDP transport interface to use for
- * sending data over the network.
- * @param[in] timeServer The IPv4 address of the server to send the
- * SNTP request packet to.
- * @param[in] serverPort The port of the @p timeServer to send the
- * request to.
- * @param[in] getTimeFunc The function to query system time for
- * tracking retry time period of no data transmissions.
- * @param[in] pPacket The buffer containing the SNTP packet data
- * to send over the network.
- * @param[in] packetSize The size of data in the SNTP request packet.
- * @param[in] timeoutMs The timeout period for retry attempts of sending
- * SNTP request packet over the network.
- *
- * @return Returns #SntpSuccess on successful transmission of the entire
- * SNTP request packet over the network; #SntpErrorNetworkFailure
- * to indicate failure from transport interface; #SntpErrorSendTimeout if
- * time request could not be sent over the network within the @p timeoutMs
- * duration.
- */
-static SntpStatus_t sendSntpPacket( const UdpTransportInterface_t * pNetworkIntf,
- uint32_t timeServer,
- uint16_t serverPort,
- SntpGetTime_t getTimeFunc,
- const uint8_t * pPacket,
- uint16_t packetSize,
- uint32_t timeoutMs )
-{
- const uint8_t * pIndex = pPacket;
- int32_t bytesSent = 0;
- SntpTimestamp_t lastSendTime;
- bool shouldRetry = false;
- SntpStatus_t status = SntpErrorSendTimeout;
-
- assert( pPacket != NULL );
- assert( getTimeFunc != NULL );
- assert( pNetworkIntf != NULL );
- assert( packetSize >= SNTP_PACKET_BASE_SIZE );
-
- /* Record the starting time of attempting to send data. This begins the retry timeout
- * window. */
- getTimeFunc( &lastSendTime );
-
- /* Loop until the entire packet is sent. */
- do
- {
- /* Reset flag for retrying send operation for the iteration. If request packet cannot be
- * sent and timeout has not occurred, the flag will be set later for the next iteration. */
- shouldRetry = false;
-
- bytesSent = pNetworkIntf->sendTo( pNetworkIntf->pUserContext,
- timeServer,
- serverPort,
- pIndex,
- packetSize );
-
- if( bytesSent < 0 )
- {
- LogError( ( "Unable to send request packet: Transport send failed. "
- "ErrorCode=%ld.", ( long int ) bytesSent ) );
- status = SntpErrorNetworkFailure;
- }
- else if( bytesSent == 0 )
- {
- /* No bytes were sent over the network. Retry send if we have not timed out. */
-
- SntpTimestamp_t currentTime;
- uint64_t elapsedTimeMs;
-
- getTimeFunc( ¤tTime );
-
- /* Calculate time elapsed since last data was sent over network. */
- elapsedTimeMs = calculateElapsedTimeMs( ¤tTime, &lastSendTime );
-
- /* Check for timeout if we have been waiting to send any data over the network. */
- if( elapsedTimeMs >= timeoutMs )
- {
- LogError( ( "Unable to send request packet: Timed out retrying send: "
- "SendRetryTimeout=%ums", timeoutMs ) );
- status = SntpErrorSendTimeout;
- }
- else
- {
- shouldRetry = true;
- }
- }
-
- /* Partial sends are not supported by UDP, which only supports sending the entire datagram as a whole.
- * Thus, if the transport send function returns status representing partial send, it will be treated as failure. */
- else if( bytesSent != ( int32_t ) packetSize )
- {
- LogError( ( "Unable to send request packet: Transport send returned unexpected bytes sent. "
- "ReturnCode=%ld, ExpectedCode=%u", ( long int ) bytesSent, packetSize ) );
-
- status = SntpErrorNetworkFailure;
- }
- else
- {
- /* The time request packet has been sent over the network. */
- status = SntpSuccess;
- }
- } while( shouldRetry == true );
-
- return status;
-}
-
-/**
- * @brief Adds client authentication data to SNTP request packet by calling the
- * authentication interface.
- *
- * @param[in] pContext The SNTP context.
- *
- * @return Returns one of the following:
- * - #SntpSuccess if the interface function successfully appends client
- * authentication data.
- * - #SntpErrorAuthFailure when the interface returns either an error OR an
- * incorrect size of the client authentication data.
- */
-static SntpStatus_t addClientAuthentication( SntpContext_t * pContext )
-{
- SntpStatus_t status = SntpSuccess;
- uint16_t authDataSize = 0U;
-
- assert( pContext != NULL );
- assert( pContext->authIntf.generateClientAuth != NULL );
- assert( pContext->currentServerIndex <= pContext->numOfServers );
-
- status = pContext->authIntf.generateClientAuth( pContext->authIntf.pAuthContext,
- &pContext->pTimeServers[ pContext->currentServerIndex ],
- pContext->pNetworkBuffer,
- pContext->bufferSize,
- &authDataSize );
-
- if( status != SntpSuccess )
- {
- LogError( ( "Unable to send time request: Client authentication function failed: "
- "RetStatus=%s", Sntp_StatusToStr( status ) ) );
- }
-
- /* Sanity check that the returned authentication data size fits in the remaining space
- * of the request buffer besides the first #SNTP_PACKET_BASE_SIZE bytes. */
- else if( authDataSize > ( pContext->bufferSize - SNTP_PACKET_BASE_SIZE ) )
- {
- LogError( ( "Unable to send time request: Invalid authentication code size: "
- "AuthCodeSize=%lu, NetworkBufferSize=%lu",
- ( unsigned long ) authDataSize, ( unsigned long ) pContext->bufferSize ) );
- status = SntpErrorAuthFailure;
- }
- else
- {
- /* With the authentication data added. calculate total SNTP request packet size. The same
- * size would be expected in the SNTP response from server. */
- pContext->sntpPacketSize = SNTP_PACKET_BASE_SIZE + authDataSize;
-
- LogInfo( ( "Appended client authentication code to SNTP request packet:"
- " AuthCodeSize=%lu, TotalPacketSize=%lu",
- ( unsigned long ) authDataSize,
- ( unsigned long ) pContext->sntpPacketSize ) );
- }
-
- return status;
-}
-
-SntpStatus_t Sntp_SendTimeRequest( SntpContext_t * pContext,
- uint32_t randomNumber,
- uint32_t blockTimeMs )
-{
- SntpStatus_t status = SntpSuccess;
-
- /* Validate the context parameter. */
- status = validateContext( pContext );
-
- if( status == SntpSuccess )
- {
- const SntpServerInfo_t * pServer = NULL;
-
- /* Set local variable for the currently indexed server to use for time
- * query. */
- pServer = &pContext->pTimeServers[ pContext->currentServerIndex ];
-
- LogDebug( ( "Using server %.*s for time query", ( int ) pServer->serverNameLen, pServer->pServerName ) );
-
- /* Perform DNS resolution of the currently indexed server in the list
- * of configured servers. */
- if( pContext->resolveDnsFunc( pServer, &pContext->currentServerAddr ) == false )
- {
- LogError( ( "Unable to send time request: DNS resolution failed: Server=%.*s",
- ( int ) pServer->serverNameLen, pServer->pServerName ) );
-
- status = SntpErrorDnsFailure;
- }
- else
- {
- LogDebug( ( "Server DNS resolved: Address=0x%08X", pContext->currentServerAddr ) );
- }
-
- if( status == SntpSuccess )
- {
- /* Obtain current system time to generate SNTP request packet. */
- pContext->getTimeFunc( &pContext->lastRequestTime );
-
- LogDebug( ( "Obtained current time for SNTP request packet: Time=%us %ums",
- pContext->lastRequestTime.seconds, FRACTIONS_TO_MS( pContext->lastRequestTime.fractions ) ) );
-
- /* Generate SNTP request packet with the current system time and
- * the passed random number. */
- status = Sntp_SerializeRequest( &pContext->lastRequestTime,
- randomNumber,
- pContext->pNetworkBuffer,
- pContext->bufferSize );
-
- /* The serialization should be successful as all parameter validation has
- * been done before. */
- assert( status == SntpSuccess );
- }
-
- /* If an authentication interface has been configured, call the function to append client
- * authentication data to SNTP request buffer. */
- if( ( status == SntpSuccess ) && ( pContext->authIntf.generateClientAuth != NULL ) )
- {
- status = addClientAuthentication( pContext );
- }
-
- if( status == SntpSuccess )
- {
- LogInfo( ( "Sending serialized SNTP request packet to the server: Addr=%u, Port=%u",
- pContext->currentServerAddr,
- pContext->pTimeServers[ pContext->currentServerIndex ].port ) );
-
- /* Send the request packet over the network to the time server. */
- status = sendSntpPacket( &pContext->networkIntf,
- pContext->currentServerAddr,
- pContext->pTimeServers[ pContext->currentServerIndex ].port,
- pContext->getTimeFunc,
- pContext->pNetworkBuffer,
- pContext->sntpPacketSize,
- blockTimeMs );
- }
- }
-
- return status;
-}
-
-/**
- * @brief Utility to update the SNTP context to rotate the server of use for subsequent
- * time request(s).
- *
- * @note If there is no next server remaining, after the current server's index, in the list of
- * configured servers, the server rotation algorithm wraps around to the first server in the list.
- * The wrap around is done so that an application using the library for a long-running SNTP client
- * functionality (like a daemon task) does not become dysfunctional after all configured time
- * servers have been used up. Time synchronization can be a critical functionality for a system
- * and the wrap around logic ensures that the SNTP client continues to function in such a case.
- *
- * @note Server rotation is performed ONLY when either of:
- * - The current server responds with a rejection for time request.
- * OR
- * - The current server response wait has timed out.
- */
-static void rotateServerForNextTimeQuery( SntpContext_t * pContext )
-{
- size_t nextServerIndex = ( pContext->currentServerIndex + 1U ) % pContext->numOfServers;
-
- LogInfo( ( "Rotating server for next time query: PreviousServer=%.*s, NextServer=%.*s",
- ( int ) pContext->pTimeServers[ pContext->currentServerIndex ].serverNameLen,
- pContext->pTimeServers[ pContext->currentServerIndex ].pServerName,
- ( int ) pContext->pTimeServers[ nextServerIndex ].serverNameLen,
- pContext->pTimeServers[ nextServerIndex ].pServerName ) );
-
- pContext->currentServerIndex = nextServerIndex;
-}
-
-
-/**
- * @brief This function attempts to receive the SNTP response packet from a server.
- *
- * @note This function treats reads of data sizes less than the expected server response packet,
- * as an error as UDP does not support partial reads. Such a scenario can exist either due:
- * - An error in the server sending its response with smaller packet size than the request packet OR
- * - A malicious attacker spoofing or modifying server response OR
- * - An error in the UDP transport interface implementation for read operation.
- *
- * @param[in] pTransportIntf The UDP transport interface to use for receiving data from
- * the network.
- * @param[in] timeServer The server to read the response from the network.
- * @param[in] serverPort The port of the server to read the response from.
- * @param[in, out] pBuffer This will be filled with the server response read from the
- * network.
- * @param[in] responseSize The size of server response to read from the network.
- *
- * @return It returns one of the following:
- * - #SntpSuccess if an SNTP response packet is received from the network.
- * - #SntpNoResponseReceived if a server response is not received from the network.
- * - #SntpErrorNetworkFailure if there is an internal failure in reading from the network
- * in the user-defined transport interface.
- */
-static SntpStatus_t receiveSntpResponse( const UdpTransportInterface_t * pTransportIntf,
- uint32_t timeServer,
- uint16_t serverPort,
- uint8_t * pBuffer,
- uint16_t responseSize )
-{
- SntpStatus_t status = SntpNoResponseReceived;
- int32_t bytesRead = 0;
-
- assert( pTransportIntf != NULL );
- assert( pTransportIntf->recvFrom != NULL );
- assert( pBuffer != NULL );
- assert( responseSize >= SNTP_PACKET_BASE_SIZE );
-
- bytesRead = pTransportIntf->recvFrom( pTransportIntf->pUserContext,
- timeServer,
- serverPort,
- pBuffer,
- responseSize );
-
- /* Negative return code indicates error. */
- if( bytesRead < 0 )
- {
- status = SntpErrorNetworkFailure;
- LogError( ( "Unable to receive server response: Transport receive failed: Code=%ld",
- ( long int ) bytesRead ) );
- }
- /* If the packet was not available on the network, check whether we can retry. */
- else if( bytesRead == 0 )
- {
- status = SntpNoResponseReceived;
- }
-
- /* Partial reads are not supported by UDP, which only supports receiving the entire datagram as a whole.
- * Thus, if the transport receive function returns reception of partial data, it will be treated as failure. */
- else if( bytesRead != ( int32_t ) responseSize )
- {
- LogError( ( "Failed to receive server response: Transport recv returned less than expected bytes."
- "ExpectedBytes=%u, ReadBytes=%ld", responseSize, ( long int ) bytesRead ) );
- status = SntpErrorNetworkFailure;
- }
- else
- {
- LogDebug( ( "Received server response: PacketSize=%ld", ( long int ) bytesRead ) );
- status = SntpSuccess;
- }
-
- return status;
-}
-
-/**
- * @brief Processes the response from a server by de-serializing the SNTP packet to
- * validate the server (if an authentication interface has been configured), determine
- * whether server has accepted or rejected the time request, and update the system clock
- * if the server responded positively with time.
- *
- * @param[in] pContext The SNTP context representing the SNTP client.
- * @param[in] pResponseRxTime The time of receiving the server response from the network.
- *
- * @return It returns one of the following:
- * - #SntpSuccess if the server response is successfully de-serialized and system clock
- * updated.
- * - #SntpErrorAuthFailure if there is internal failure in user-defined authentication
- * interface when validating server from the response.
- * - #SntpServerNotAuthenticated if the server failed authenticated check in the user-defined
- * interface.
- * - #SntpRejectedResponse if the server has rejected the time request in its response.
- * - #SntpInvalidResponse if the server response failed sanity checks.
- */
-static SntpStatus_t processServerResponse( SntpContext_t * pContext,
- const SntpTimestamp_t * pResponseRxTime )
-{
- SntpStatus_t status = SntpSuccess;
- const SntpServerInfo_t * pServer = &pContext->pTimeServers[ pContext->currentServerIndex ];
-
- assert( pContext != NULL );
- assert( pResponseRxTime != NULL );
-
- if( pContext->authIntf.validateServerAuth != NULL )
- {
- /* Verify the server from the authentication data in the SNTP response packet. */
- status = pContext->authIntf.validateServerAuth( pContext->authIntf.pAuthContext,
- pServer,
- pContext->pNetworkBuffer,
- pContext->sntpPacketSize );
- assert( ( status == SntpSuccess ) || ( status == SntpErrorAuthFailure ) ||
- ( status == SntpServerNotAuthenticated ) );
-
- if( status != SntpSuccess )
- {
- LogError( ( "Unable to use server response: Server authentication function failed: "
- "ReturnStatus=%s", Sntp_StatusToStr( status ) ) );
- }
- else
- {
- LogDebug( ( "Server response has been validated: Server=%.*s", ( int ) pServer->serverNameLen, pServer->pServerName ) );
- }
- }
-
- if( status == SntpSuccess )
- {
- SntpResponseData_t parsedResponse;
-
- /* De-serialize response packet to determine whether the server accepted or rejected
- * the request for time. Also, calculate the system clock offset if the server responded
- * with time. */
- status = Sntp_DeserializeResponse( &pContext->lastRequestTime,
- pResponseRxTime,
- pContext->pNetworkBuffer,
- pContext->sntpPacketSize,
- &parsedResponse );
-
- /* We do not expect the following errors to be returned as the context
- * has been validated in the Sntp_ReceiveTimeResponse API. */
- assert( status != SntpErrorBadParameter );
- assert( status != SntpErrorBufferTooSmall );
-
- if( ( status == SntpRejectedResponseChangeServer ) ||
- ( status == SntpRejectedResponseRetryWithBackoff ) ||
- ( status == SntpRejectedResponseOtherCode ) )
- {
- /* Server has rejected the time request. Thus, we will rotate to the next time server
- * in the list. */
- rotateServerForNextTimeQuery( pContext );
-
- LogError( ( "Unable to use server response: Server has rejected request for time: RejectionCode=%.*s",
- ( int ) SNTP_KISS_OF_DEATH_CODE_LENGTH, ( char * ) &parsedResponse.rejectedResponseCode ) );
- status = SntpRejectedResponse;
- }
- else if( status == SntpInvalidResponse )
- {
- LogError( ( "Unable to use server response: Server response failed sanity checks." ) );
- }
- else
- {
- /* Server has responded successfully with time, and we have calculated the clock offset
- * of system clock relative to the server.*/
- LogDebug( ( "Updating system time: ServerTime=%u %ums ClockOffset=%lums",
- parsedResponse.serverTime.seconds, FRACTIONS_TO_MS( parsedResponse.serverTime.fractions ),
- parsedResponse.clockOffsetMs ) );
-
- /* Update the system clock with the calculated offset. */
- pContext->setTimeFunc( pServer, &parsedResponse.serverTime,
- parsedResponse.clockOffsetMs, parsedResponse.leapSecondType );
-
- status = SntpSuccess;
- }
- }
-
- /* Reset the last request time state in context to protect against replay attacks.
- * Note: The last request time is not cleared when a rejection response packet is received and the client does
- * has not authenticated server from the response. This is because clearing of the state causes the coreSNTP
- * library to discard any subsequent server response packets (as the "originate timestamp" of those packets will
- * not match the last request time value of the context), and thus, an attacker can cause Denial of Service
- * attacks by spoofing server response before the actual server is able to respond.
- */
- if( ( status == SntpSuccess ) ||
- ( ( pContext->authIntf.validateServerAuth != NULL ) && ( status == SntpRejectedResponse ) ) )
- {
- /* In the attack of SNTP request packet being replayed, the replayed request packet is serviced by
- * SNTP/NTP server with SNTP response (as servers are stateless) and client receives the response
- * containing new values of server timestamps but the stale value of "originate timestamp".
- * To prevent the coreSNTP library from servicing such a server response (associated with the replayed
- * SNTP request packet), the last request timestamp state is cleared in the context after receiving the
- * first valid server response. Therefore, any subsequent server response(s) from replayed client request
- * packets can be invalidated due to the "originate timestamp" not matching the last request time stored
- * in the context.
- * Note: If an attacker spoofs a server response with a zero "originate timestamp" after the coreSNTP
- * library (i.e. the SNTP client) has cleared the internal state to zero, the spoofed packet will be
- * discarded as the coreSNTP serializer does not accept server responses with zero value for timestamps.
- */
- pContext->lastRequestTime.seconds = 0U;
- pContext->lastRequestTime.fractions = 0U;
- }
-
- return status;
-}
-
-/**
- * @brief Determines whether a retry attempt should be made to receive server response packet from the network
- * depending on the timing constraints of server response timeout, @p responseTimeoutMs, and the block time
- * period, @p blockTimeMs, passed. If neither of the time windows have expired, the function determines that the
- * read operation can be re-tried.
- *
- * @param[in] pCurrentTime The current time in the system used for calculating elapsed time windows.
- * @param[in] pReadStartTime The time of the first read attempt in the current set of read tries occurring
- * from the Sntp_ReceiveTimeRequest API call by the application. This time is used for calculating the elapsed
- * time to determine whether the block time has expired.
- * @param[in] pRequestTime The time of sending the SNTP request to the server for which the response is
- * awaited. This time is used for calculating total elapsed elapsed time of waiting for server response to
- * determine if a server response timeout has occurred.
- * @param[in] responseTimeoutMs The server response timeout configuration.
- * @param[in] blockTimeMs The maximum block time of waiting for server response across read tries in the current
- * call made by application to Sntp_ReceiveTimeResponse API.
- * @param[out] pHasResponseTimedOut This will be populated with state to indicate whether the wait for server
- * response has timed out.
- *
- * @return Returns true for retrying read operation of server response; false on either server response timeout
- * OR completion of block time window.
- */
-static bool decideAboutReadRetry( const SntpTimestamp_t * pCurrentTime,
- const SntpTimestamp_t * pReadStartTime,
- const SntpTimestamp_t * pRequestTime,
- uint32_t responseTimeoutMs,
- uint32_t blockTimeMs,
- bool * pHasResponseTimedOut )
-{
- uint64_t timeSinceRequestMs = 0UL;
- uint64_t timeElapsedInReadAttempts = 0UL;
- bool shouldRetry = false;
-
- assert( pCurrentTime != NULL );
- assert( pReadStartTime != NULL );
- assert( pRequestTime != NULL );
- assert( pHasResponseTimedOut != NULL );
-
- /* Calculate time elapsed since the time request was sent to the server
- * to determine whether the server response has timed out. */
- timeSinceRequestMs = calculateElapsedTimeMs( pCurrentTime, pRequestTime );
-
- /* Calculate the time elapsed across all the read attempts so far to determine
- * whether the block time window for reading server response has expired. */
- timeElapsedInReadAttempts = calculateElapsedTimeMs( pCurrentTime, pReadStartTime );
-
- /* Check whether a response timeout has occurred to inform whether we should
- * wait for server response anymore. */
- if( timeSinceRequestMs >= ( uint64_t ) responseTimeoutMs )
- {
- shouldRetry = false;
- *pHasResponseTimedOut = true;
-
- LogError( ( "Unable to receive response: Server response has timed out: "
- "RequestTime=%us %ums, TimeoutDuration=%ums, ElapsedTime=%lu",
- pRequestTime->seconds, FRACTIONS_TO_MS( pRequestTime->fractions ),
- responseTimeoutMs, timeSinceRequestMs ) );
- }
- /* Check whether the block time window has expired to determine whether read can be retried. */
- else if( timeElapsedInReadAttempts >= ( uint64_t ) blockTimeMs )
- {
- shouldRetry = false;
- LogDebug( ( "Did not receive server response: Read block time has expired: "
- "BlockTime=%ums, ResponseWaitElapsedTime=%lums",
- blockTimeMs, timeSinceRequestMs ) );
- }
- else
- {
- shouldRetry = true;
- LogDebug( ( "Did not receive server response: Retrying read: "
- "BlockTime=%ums, ResponseWaitElapsedTime=%lums, ResponseTimeout=%u",
- blockTimeMs, timeSinceRequestMs, responseTimeoutMs ) );
- }
-
- return shouldRetry;
-}
-
-SntpStatus_t Sntp_ReceiveTimeResponse( SntpContext_t * pContext,
- uint32_t blockTimeMs )
-{
- SntpStatus_t status = SntpNoResponseReceived;
- bool hasResponseTimedOut = false;
-
- /* Validate the context parameter. */
- status = validateContext( pContext );
-
- if( status == SntpSuccess )
- {
- SntpTimestamp_t startTime, currentTime;
- const SntpTimestamp_t * pRequestTime = &pContext->lastRequestTime;
- bool shouldRetry = false;
-
- /* Record time before read attempts so that it can be used as base time for
- * for tracking the block time window across read retries. */
- pContext->getTimeFunc( &startTime );
-
- do
- {
- /* Reset the retry read operation flag. If the server response is not received in the current iteration's read
- * attempt and the wait has not timed out, the flag will be set to perform a retry. */
- shouldRetry = false;
-
- /* Make an attempt to read the server response from the network. */
- status = receiveSntpResponse( &pContext->networkIntf,
- pContext->currentServerAddr,
- pContext->pTimeServers[ pContext->currentServerIndex ].port,
- pContext->pNetworkBuffer,
- pContext->sntpPacketSize );
-
- /* If the server response is received, deserialize it, validate the server
- * (if authentication interface is provided), and update system time with
- * the calculated clock offset. */
- if( status == SntpSuccess )
- {
- /* Get current time to de-serialize the receive server response packet. */
- pContext->getTimeFunc( ¤tTime );
-
- status = processServerResponse( pContext, ¤tTime );
- }
- else if( status == SntpNoResponseReceived )
- {
- /* Get current time to determine whether another attempt for reading the packet can
- * be made. */
- pContext->getTimeFunc( ¤tTime );
-
- /* Set the flag to retry read of server response from the network. */
- shouldRetry = decideAboutReadRetry( ¤tTime,
- &startTime,
- pRequestTime,
- pContext->responseTimeoutMs,
- blockTimeMs,
- &hasResponseTimedOut );
- }
- else
- {
- /* Empty else marker. */
- }
- } while( shouldRetry == true );
-
- /* If the wait for server response to the time request has timed out, rotate the server of use in the
- * context for subsequent time request(s). Also, update the return status to indicate response timeout. */
- if( hasResponseTimedOut == true )
- {
- status = SntpErrorResponseTimeout;
-
- /* Rotate server to the next in the list of configured servers in the context. */
- rotateServerForNextTimeQuery( pContext );
- }
- }
-
- return status;
-}
-
-const char * Sntp_StatusToStr( SntpStatus_t status )
-{
- const char * pString = NULL;
-
- switch( status )
- {
- case SntpSuccess:
- pString = "SntpSuccess";
- break;
-
- case SntpErrorBadParameter:
- pString = "SntpErrorBadParameter";
- break;
-
- case SntpRejectedResponseChangeServer:
- pString = "SntpRejectedResponseChangeServer";
- break;
-
- case SntpRejectedResponseRetryWithBackoff:
- pString = "SntpRejectedResponseRetryWithBackoff";
- break;
-
- case SntpRejectedResponseOtherCode:
- pString = "SntpRejectedResponseOtherCode";
- break;
-
- case SntpErrorBufferTooSmall:
- pString = "SntpErrorBufferTooSmall";
- break;
-
- case SntpInvalidResponse:
- pString = "SntpInvalidResponse";
- break;
-
- case SntpZeroPollInterval:
- pString = "SntpZeroPollInterval";
- break;
-
- case SntpErrorTimeNotSupported:
- pString = "SntpErrorTimeNotSupported";
- break;
-
- case SntpErrorDnsFailure:
- pString = "SntpErrorDnsFailure";
- break;
-
- case SntpErrorNetworkFailure:
- pString = "SntpErrorNetworkFailure";
- break;
-
- case SntpServerNotAuthenticated:
- pString = "SntpServerNotAuthenticated";
- break;
-
- case SntpErrorAuthFailure:
- pString = "SntpErrorAuthFailure";
- break;
-
- default:
- pString = "Invalid status code!";
- break;
- }
-
- return pString;
-}
diff --git a/project/coreMQTT/coreSNTP/core_sntp_client.h b/project/coreMQTT/coreSNTP/core_sntp_client.h
deleted file mode 100644
index 829aed5..0000000
--- a/project/coreMQTT/coreSNTP/core_sntp_client.h
+++ /dev/null
@@ -1,655 +0,0 @@
-/*
- * coreSNTP v1.2.0
- * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_sntp_client.h
- * @brief API of an SNTPv4 client library that can send time requests and receive time response to/from
- * SNTP/NTP servers. The library follows the Best Practices suggested in the the SNTPv4 specification,
- * [RFC 4330](https://tools.ietf.org/html/rfc4330).
- * The library can be used to run an SNTP client in a dedicated deamon task to periodically synchronize
- * time from the Internet.
- */
-
-#ifndef CORE_SNTP_CLIENT_H_
-#define CORE_SNTP_CLIENT_H_
-
-/* Standard include. */
-#include <stdint.h>
-#include <stddef.h>
-#include <stdbool.h>
-
-/* Include coreSNTP Serializer header. */
-#include "core_sntp_serializer.h"
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/**
- * @ingroup sntp_constants
- * @brief The default UDP port supported by SNTP/NTP servers for client-server
- * communication.
- *
- * @note It is possible for a server to use a different port number than
- * the default port when using the Network Time Security protocol as the security
- * mechanism for SNTP communication. For more information, refer to Section 4.1.8
- * of [RFC 8915](https://tools.ietf.org/html/rfc8915).
- */
-#define SNTP_DEFAULT_SERVER_PORT ( 123U )
-
-/**
- * @ingroup sntp_struct_types
- * @brief Structure representing information for a time server.
- */
-typedef struct SntpServerInfo
-{
- const char * pServerName; /**<@brief The time server name. */
- size_t serverNameLen; /**<@brief The length of the server name.*/
- uint16_t port; /**<@brief The UDP port supported by the server
- * for SNTP/NTP communication. */
-} SntpServerInfo_t;
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to resolve time server domain-name
- * to an IPv4 address.
- * The SNTP client library attempts to resolve the DNS of the time-server being
- * used every time the @ref Sntp_SendTimeRequest API is called.
- *
- * @param[in] pServerAddr The time-server whose IPv4 address is to be resolved.
- * @param[out] pIpV4Addr This should be filled with the resolved IPv4 address.
- * of @p pTimeServer.
- *
- * @return `true` if DNS resolution is successful; otherwise `false` to represent
- * failure.
- */
-typedef bool ( * SntpResolveDns_t )( const SntpServerInfo_t * pServerAddr,
- uint32_t * pIpV4Addr );
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to obtain the current system time
- * in SNTP timestamp format.
- *
- * @note If your platform follows UNIX representation of time, the
- * #SNTP_TIME_AT_UNIX_EPOCH_SECS and #SNTP_FRACTION_VALUE_PER_MICROSECOND macros
- * can be used to convert UNIX time to SNTP timestamp.
- *
- * @param[out] pCurrentTime This should be filled with the current system time
- * in SNTP timestamp format.
- *
- * @return `true` if obtaining system time is successful; otherwise `false` to
- * represent failure.
- */
-typedef void ( * SntpGetTime_t )( SntpTimestamp_t * pCurrentTime );
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to update the system clock time
- * so that it is synchronized the time server used for getting current time.
- *
- * @param[in] pTimeServer The time server used to request time.
- * @param[in] pServerTime The current time returned by the @p pTimeServer.
- * @param[in] clockOffsetMs The calculated clock offset (in milliseconds) of the
- * system relative to the server time.
- * @param[in] leapSecondInfo Information about whether there is about an upcoming
- * leap second adjustment of insertion or deletion in the last minute before midnight
- * on the last day of the current month. For more information on leap seconds, refer
- * to https://www.nist.gov/pml/time-and-frequency-division/leap-seconds-faqs. Depending
- * on the accuracy requirements of the system clock, the user can choose to account
- * for the leap second or ignore it in their system clock update logic.
- *
- * @note If the @p clockOffsetMs is positive, then the system time is BEHIND the server time,
- * and if the @p clockOffsetMs, the system time is AHEAD of the server time. To correct the
- * system time, the user can use either of "step", "slew" OR combination of the two clock
- * discipline methodologies depending on the application needs.
- * If the application requires a smooth time continuum of system time, then the "slew"
- * discipline methodology can be used with the clock offset value, @p clockOffSetMs, to correct
- * the system clock gradually with a "slew rate".
- * If the application can accept sudden jump in time (forward or backward), then
- * the "step" discipline methodology can be used to directly update the system
- * clock with the current server time, @p pServerTime, every time the coreSNTP library
- * calls the interface.
- */
-typedef void ( * SntpSetTime_t )( const SntpServerInfo_t * pTimeServer,
- const SntpTimestamp_t * pServerTime,
- int64_t clockOffsetMs,
- SntpLeapSecondInfo_t leapSecondInfo );
-
-/**
- * @ingroup sntp_struct_types
- * @typedef NetworkContext_t
- * @brief A user-defined type for context that is passed to the transport interface functions.
- * It MUST be defined by the user to use the library.
- * It is of incomplete type to allow user to define to the needs of their transport
- * interface implementation.
- */
-struct NetworkContext;
-typedef struct NetworkContext NetworkContext_t;
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to send time request as a single datagram
- * to server on the network over User Datagram Protocol (UDP).
- *
- * @note It is RECOMMENDED that the send operation is non-blocking, i.e. it
- * SHOULD immediately return when the entire UDP data cannot be sent over the
- * network. In such a case, the coreSNTP library will re-try send operation
- * for a maximum period of blocking time passed to the @ref Sntp_SendTimeRequest API.
- *
- * @note If the size of the SNTP packet exceeds the Maximum Transmission Unit (MTU)
- * supported by the network interface of the device, the user-defined implementation
- * MAY either support fragmentation of UDP packets OR use a size for authentication data
- * that allows the SNTP packet to fit within the MTU required size threshold. (Note that
- * the size of SNTP packet is #SNTP_PACKET_BASE_SIZE + authentication data.)
- *
- * @param[in,out] pNetworkContext The user defined NetworkContext_t which
- * is opaque to the coreSNTP library.
- * @param[in] serverAddr The IPv4 address of the time server to send the data to.
- * @param[in] serverPort The port of the server to send data to.
- * @param[in] pBuffer The buffer containing the data to send over the network.
- * @param[in] bytesToSend The size of data in @p pBuffer to send.
- *
- * @return The function SHOULD return one of the following integer codes:
- * - @p bytesToSend when all requested data is successfully transmitted over the
- * network.
- * - 0 when no data could be sent over the network (due to network buffer being
- * full, for example), and the send operation can be retried.
- * - < 0 when the send operation failed to send any data due to an internal error,
- * and operation cannot be retried.
- */
-typedef int32_t ( * UdpTransportSendTo_t )( NetworkContext_t * pNetworkContext,
- uint32_t serverAddr,
- uint16_t serverPort,
- const void * pBuffer,
- uint16_t bytesToSend );
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to receive the server response, to a time
- * request (sent through the @ref UdpTransportSendTo_t function), from the network over
- * User Datagram Protocol (UDP).
- *
- * @note It is RECOMMENDED that the read operation is non-blocking, i.e. it
- * SHOULD immediately return when no data is available on the network.
- * In such a case, the coreSNTP library will re-try send operation for a maximum period
- * of blocking time passed through the @ref Sntp_ReceiveTimeResponse API.
- *
- * @note If the size of the SNTP response packet from the server exceeds the
- * Maximum Transmission Unit (MTU) supported by the network interface of the device,
- * the user-defined implementation of the interface MAY either support receiving and
- * assembling fragmented UDP packets OR use an authentication data size that allows
- * SNTP packet to fit within the MTU required packet size threshold. (Note that
- * the size of SNTP packet is #SNTP_PACKET_BASE_SIZE + authentication data.)
- *
- * @param[in,out] pNetworkContext The user defined NetworkContext_t which
- * is opaque to the coreSNTP library.
- * @param[in] serverAddr The IPv4 address of the time server to receive data from.
- * @param[in] serverPort The port of the server to receive data from.
- * @param[out] pBuffer This SHOULD be filled with data received from the network.
- * @param[in] bytesToRecv The expected number of bytes to receive from the
- * server.
- *
- * @return The function SHOULD return one of the following integer codes:
- * - @p bytesToRecv value if all the requested number of bytes are received
- * from the network.
- * - ZERO when no data is available on the network, and the operation can be
- * retried.
- * - < 0 when the read operation failed due to internal error, and operation cannot
- * be retried.
- */
-typedef int32_t ( * UdpTransportRecvFrom_t )( NetworkContext_t * pNetworkContext,
- uint32_t serverAddr,
- uint16_t serverPort,
- void * pBuffer,
- uint16_t bytesToRecv );
-
-/**
- * @ingroup sntp_struct_types
- * @brief Struct representing the UDP transport interface for user-defined functions
- * that coreSNTP library depends on for performing read/write network operations.
- */
-typedef struct UdpTransportIntf
-{
- NetworkContext_t * pUserContext; /**<@brief The user-defined context for storing
- * network socket information. */
- UdpTransportSendTo_t sendTo; /**<@brief The user-defined UDP send function. */
- UdpTransportRecvFrom_t recvFrom; /**<@brief The user-defined UDP receive function. */
-} UdpTransportInterface_t;
-
-/**
- * @ingroup sntp_struct_types
- * @typedef SntpAuthContext_t
- * @brief A user-defined type for context that is passed to the authentication interface functions.
- * It MUST be defined by the user to use the library.
- * It is of incomplete type to allow user to defined to the the needs of their authentication
- * interface implementation.
- */
-struct SntpAuthContext;
-typedef struct SntpAuthContext SntpAuthContext_t;
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to generate and append
- * authentication code in an SNTP request buffer for the SNTP client to be
- * authenticated by the time server, if a security mechanism is used.
- *
- * The user can choose to implement with any security mechanism, symmetric
- * key-based (like AES-CMAC) or asymmetric key-based (like Network Time Security),
- * depending on the security mechanism supported by the time server being used
- * to synchronize time with.
- *
- * @note The function SHOULD generate the authentication data for the first
- * #SNTP_PACKET_BASE_SIZE bytes of SNTP request packet present in the passed buffer
- * @p pBuffer, and fill the generated authentication data after #SNTP_PACKET_BASE_SIZE
- * bytes in the buffer.
- *
- * @param[in,out] pContext The user defined NetworkContext_t which
- * is opaque to the coreSNTP library.
- * @param[in] pTimeServer The time server being used to request time from.
- * This parameter is useful to choose the security mechanism when multiple time
- * servers are configured in the library, and they require different security
- * mechanisms or authentication credentials to use.
- * @param[in, out] pBuffer This buffer SHOULD be filled with the authentication
- * code generated from the #SNTP_PACKET_BASE_SIZE bytes of SNTP request data
- * present in it.
- * @param[in] bufferSize The maximum amount of data that can be held by the buffer,
- * @p pBuffer.
- * @param[out] pAuthCodeSize This should be filled with size of the authentication
- * data appended to the SNTP request buffer, @p pBuffer. This value plus
- * #SNTP_PACKET_BASE_SIZE should not exceed the buffer size, @p bufferSize.
- *
- * @return The function SHOULD return one of the following integer codes:
- * - #SntpSuccess when the authentication data is successfully appended to @p pBuffer.
- * - #SntpErrorBufferTooSmall when the user-supplied buffer (to the SntpContext_t through
- * @ref Sntp_Init) is not large enough to hold authentication data.
- * - #SntpErrorAuthFailure for failure to generate authentication data due to internal
- * error.
- */
-typedef SntpStatus_t (* SntpGenerateAuthCode_t )( SntpAuthContext_t * pContext,
- const SntpServerInfo_t * pTimeServer,
- void * pBuffer,
- size_t bufferSize,
- uint16_t * pAuthCodeSize );
-
-/**
- * @ingroup sntp_callback_types
- * @brief Interface for user-defined function to authenticate server by validating
- * the authentication code present in its SNTP response to a time request, if
- * a security mechanism is supported by the server.
- *
- * The user can choose to implement with any security mechanism, symmetric
- * key-based (like AES-CMAC) or asymmetric key-based (like Network Time Security),
- * depending on the security mechanism supported by the time server being used
- * to synchronize time with.
- *
- * @note In an SNTP response, the authentication code is present only after the
- * first #SNTP_PACKET_BASE_SIZE bytes. Depending on the security mechanism used,
- * the first #SNTP_PACKET_BASE_SIZE bytes MAY be used in validating the
- * authentication data sent by the server.
- *
- * @param[in,out] pContext The user defined NetworkContext_t which
- * is opaque to the coreSNTP library.
- * @param[in] pTimeServer The time server that has to be authenticated from its
- * SNTP response.
- * This parameter is useful to choose the security mechanism when multiple time
- * servers are configured in the library, and they require different security
- * mechanisms or authentication credentials to use.
- * @param[in] pResponseData The SNTP response from the server that contains the
- * authentication code after the first #SNTP_PACKET_BASE_SIZE bytes.
- * @param[in] responseSize The total size of the response from the server.
- *
- * @return The function SHOULD return one of the following integer codes:
- * - #SntpSuccess when the server is successfully authenticated.
- * - #SntpServerNotAuthenticated when server could not be authenticated.
- * - #SntpErrorAuthFailure for failure to authenticate server due to internal
- * error.
- */
-typedef SntpStatus_t (* SntpValidateServerAuth_t )( SntpAuthContext_t * pContext,
- const SntpServerInfo_t * pTimeServer,
- const void * pResponseData,
- uint16_t responseSize );
-
-/**
- * @ingroup sntp_struct_types
- * @brief Struct representing the authentication interface for securely
- * communicating with time servers.
- *
- * @note Using a security mechanism is OPTIONAL for using the coreSNTP
- * library i.e. a user does not need to define the authentication interface
- * if they are not using a security mechanism for SNTP communication.
- */
-typedef struct SntpAuthenticationIntf
-{
- /**
- *@brief The user-defined context for storing information like
- * key credentials required for cryptographic operations in the
- * security mechanism used for communicating with server.
- */
- SntpAuthContext_t * pAuthContext;
-
- /**
- * @brief The user-defined function for appending client authentication data.
- * */
- SntpGenerateAuthCode_t generateClientAuth;
-
- /**
- * @brief The user-defined function for authenticating server from its SNTP
- * response.
- */
- SntpValidateServerAuth_t validateServerAuth;
-} SntpAuthenticationInterface_t;
-
-/**
- * @ingroup sntp_struct_types
- * @brief Structure for a context that stores state for managing a long-running
- * SNTP client that periodically polls time and synchronizes system clock.
- */
-typedef struct SntpContext
-{
- /**
- * @brief List of time servers in decreasing priority order configured
- * for the SNTP client.
- * Only a single server is configured for use at a time across polling
- * attempts until the server rejects a time request or there is a response
- * timeout, after which, the next server in the list is used for subsequent
- * polling requests.
- */
- const SntpServerInfo_t * pTimeServers;
-
- /**
- * @brief Number of servers configured for use.
- */
- size_t numOfServers;
-
- /**
- * @brief The index for the currently configured time server for time querying
- * from the list of time servers in @ref pTimeServers.
- */
- size_t currentServerIndex;
-
- /**
- * @brief The user-supplied buffer for storing network data of both SNTP requests
- * and SNTP response.
- */
- uint8_t * pNetworkBuffer;
-
- /**
- * @brief The size of the network buffer.
- */
- size_t bufferSize;
-
- /**
- * @brief The user-supplied function for resolving DNS name of time servers.
- */
- SntpResolveDns_t resolveDnsFunc;
-
- /**
- * @brief The user-supplied function for obtaining the current system time.
- */
- SntpGetTime_t getTimeFunc;
-
- /**
- * @brief The user-supplied function for correcting system time after receiving
- * time from a server.
- */
- SntpSetTime_t setTimeFunc;
-
- /**
- * @brief The user-defined interface for performing User Datagram Protocol (UDP)
- * send and receive network operations.
- */
- UdpTransportInterface_t networkIntf;
-
- /**
- * @brief The user-defined interface for incorporating security mechanism of
- * adding client authentication in SNTP request as well as authenticating server
- * from SNTP response.
- *
- * @note If the application will not use security mechanism for any of the
- * configured servers, then this interface can be undefined.
- */
- SntpAuthenticationInterface_t authIntf;
-
- /**
- * @brief Cache of the resolved Ipv4 address of the current server being used for
- * time synchronization.
- * As a Best Practice functionality, the client library attempts to resolve the
- * DNS of the time-server every time the @ref Sntp_SendTimeRequest API is called.
- */
- uint32_t currentServerAddr;
-
- /**
- * @brief Cache of the timestamp of sending the last time request to a server
- * for replay attack protection by checking that the server response contains
- * the same timestamp in its "originate timestamp" field.
- */
- SntpTimestamp_t lastRequestTime;
-
- /**
- * @brief State member for storing the size of the SNTP packet that includes
- * both #SNTP_PACKET_BASE_SIZE bytes plus any authentication data, if a security
- * mechanism is used.
- * This value is used for expecting the same size for an SNTP response
- * from the server.
- */
- uint16_t sntpPacketSize;
-
- /**
- * @brief The timeout duration (in milliseconds) for receiving a response, through
- * @ref Sntp_ReceiveTimeResponse API, from a server after the request for time is
- * sent to it through @ref Sntp_SendTimeRequest API.
- */
- uint32_t responseTimeoutMs;
-} SntpContext_t;
-
-/**
- * @brief Initializes a context for SNTP client communication with SNTP/NTP
- * servers.
- *
- * @param[out] pContext The user-supplied memory for the context that will be
- * initialized to represent an SNTP client.
- * @param[in] pTimeServers The list of decreasing order of priority of time
- * servers that should be used by the SNTP client. This list MUST stay in
- * scope for all the time of use of the context.
- * @param[in] numOfServers The number of servers in the list, @p pTimeServers.
- * @param[in] serverResponseTimeoutMs The timeout duration (in milliseconds) for
- * receiving server response for time requests. The same timeout value is used for
- * each server in the @p pTimeServers list.
- * @param[in] pNetworkBuffer The user-supplied memory that will be used for
- * storing network data for SNTP client-server communication. The buffer
- * MUST stay in scope for all the time of use of the context.
- * @param[in] bufferSize The size of the passed buffer @p pNetworkBuffer. The buffer
- * SHOULD be appropriately sized for storing an entire SNTP packet which includes
- * both #SNTP_PACKET_BASE_SIZE bytes of standard SNTP packet size, and space for
- * authentication data, if security mechanism is used to communicate with any of
- * the time servers configured for use.
- * @param[in] resolveDnsFunc The user-defined function for DNS resolution of time
- * server.
- * @param[in] getSystemTimeFunc The user-defined function for querying system
- * time.
- * @param[in] setSystemTimeFunc The user-defined function for correcting system
- * time for every successful time response received from a server.
- * @param[in] pTransportIntf The user-defined function for performing network
- * send/recv operations over UDP.
- * @param[in] pAuthIntf The user-defined interface for generating client authentication
- * in SNTP requests and authenticating servers in SNTP responses, if security mechanism
- * is used in SNTP communication with server(s). If security mechanism is not used in
- * communication with any of the configured servers (in @p pTimeServers), then the
- * @ref SntpAuthenticationInterface_t does not need to be defined and this parameter
- * can be NULL.
- *
- * @return This function returns one of the following:
- * - #SntpSuccess if the context is initialized.
- * - #SntpErrorBadParameter if any of the passed parameters in invalid.
- * - #SntpErrorBufferTooSmall if the buffer does not have the minimum size
- * required for a valid SNTP response packet.
- */
-/* @[define_sntp_init] */
-SntpStatus_t Sntp_Init( SntpContext_t * pContext,
- const SntpServerInfo_t * pTimeServers,
- size_t numOfServers,
- uint32_t serverResponseTimeoutMs,
- uint8_t * pNetworkBuffer,
- size_t bufferSize,
- SntpResolveDns_t resolveDnsFunc,
- SntpGetTime_t getSystemTimeFunc,
- SntpSetTime_t setSystemTimeFunc,
- const UdpTransportInterface_t * pTransportIntf,
- const SntpAuthenticationInterface_t * pAuthIntf );
-/* @[define_sntp_init] */
-
-
-/**
- * @brief Sends a request for time from the currently configured server (in the
- * context).
- * If the user has provided an authentication interface, the client
- * authentication code is appended to the request before sending over the network
- * by calling the @ref SntpGenerateAuthCode_t function of the
- * @ref SntpAuthenticationInterface_t.
- *
- * @note This function will ONLY send a request if there is a server available
- * in the configured list that has not rejected an earlier request for time.
- * This adheres to the Best Practice functionality specified in [Section 10 Point 8
- * of SNTPv4 specification](https://tools.ietf.org/html/rfc4330#section-10).
- *
- * @param[in] pContext The context representing an SNTPv4 client.
- * @param[in] randomNumber A random number serializing the SNTP request packet
- * to protect against spoofing attacks by attackers that are off the network path
- * of the SNTP client-server communication. This mechanism is suggested by SNTPv4
- * specification in [RFC 4330 Section 3](https://tools.ietf.org/html/rfc4330#section-3).
- * @param[in] blockTimeMs The maximum duration of time (in milliseconds) the function will
- * block on attempting to send time request to the server over the network. If a zero
- * block time value is provided, then the function will attempt to send the packet ONLY
- * once.
- *
- * @note It is RECOMMENDED that a True Random Number Generator is used to generate the
- * random number by using a hardware module, like Hardware Security Module (HSM), Secure Element,
- * etc, as the entropy source.
- *
- * @return The API function returns one of the following:
- * - #SntpSuccess if a time request is successfully sent to the currently configured
- * time server in the context.
- * - #SntpErrorBadParameter if an invalid context is passed to the function.
- * - #SntpErrorContextNotInitialized if an uninitialized or invalid context is passed
- * to the function.
- * - #SntpErrorDnsFailure if there is failure in the user-defined function for
- * DNS resolution of the time server.
- * - #SntpErrorNetworkFailure if the SNTP request could not be sent over the network
- * through the user-defined transport interface.
- * - #SntpErrorAuthFailure if there was a failure in generating the client
- * authentication code in the user-defined authentication interface.
- * - #SntpErrorSendTimeout if the time request packet could not be sent over the
- * network for the entire @p blockTimeMs duration.
- */
-/* @[define_sntp_sendtimerequest] */
-SntpStatus_t Sntp_SendTimeRequest( SntpContext_t * pContext,
- uint32_t randomNumber,
- uint32_t blockTimeMs );
-/* @[define_sntp_sendtimerequest] */
-
-
-/**
- * @brief Receives a time response from the server that has been requested for time with
- * the @ref Sntp_SendTimeRequest API function.
- * Once an accepted response containing time from server is received, this function calls
- * the user-defined @ref SntpSetTime_t function to update the system time.
- *
- * @note If the user has provided an authentication interface to the client
- * (through @ref Sntp_Init), the server response is authenticated by calling the
- * @ref SntpValidateServerAuth_t function of the @ref SntpAuthenticationInterface_t interface.
- *
- * @note On receiving a successful server response containing server time,
- * this API calculates the clock offset value of the system clock relative to the
- * server before calling the user-defined @ref SntpSetTime_t function for updating
- * the system time.
- *
- * @note For correct calculation of clock-offset, the server and client times MUST be within
- * ~68 years (or 2^31 seconds) of each other. In the special case when the server and client
- * times are exactly 2^31 seconds apart, the library ASSUMES that the server time is ahead
- * of the client time, and returns the positive clock-offset value of INT32_MAX seconds.
- *
- * @note This API will rotate the server of use in the library for the next time request
- * (through the @ref Sntp_SendTimeRequest) if either of following events occur:
- * - The server has responded with a rejection for the time request.
- * OR
- * - The server response wait has timed out.
- * If all the servers configured in the context have been used, the API will rotate server for
- * time query back to the first server in the list which will be used in next time request.
- *
- * @param[in] pContext The context representing an SNTPv4 client.
- * @param[in] blockTimeMs The maximum duration of time (in milliseconds) the function will
- * block on receiving a response from the server unless either the response is received
- * OR a response timeout occurs.
- *
- * @note This function can be called multiple times with zero or small blocking times
- * to poll whether server response is received until either the response response is
- * received from the server OR a response timeout has occurred.
- *
- * @return This API functions returns one of the following:
- * - #SntpSuccess if a successful server response is received.
- * - #SntpErrorContextNotInitialized if an uninitialized or invalid context is passed
- * to the function.
- * - #SntpErrorBadParameter if an invalid context is passed to the function.
- * - #SntpErrorNetworkFailure if there is a failure in the user-defined transport
- * - #SntpErrorAuthFailure if an internal error occurs in the user-defined
- * authentication interface when validating the server response.
- * - #SntpServerNotAuthenticated when the server could not be authenticated from
- * its response with the user-defined authentication interface.
- * - #SntpInvalidResponse if the server response fails sanity checks expected in an
- * SNTP response packet.
- * - #SntpErrorResponseTimeout if a timeout has occurred in receiving response from
- * the server.
- * - #SntpRejectedResponse if the server responded with a rejection for the time
- * request.
- */
-/* @[define_sntp_receivetimeresponse] */
-SntpStatus_t Sntp_ReceiveTimeResponse( SntpContext_t * pContext,
- uint32_t blockTimeMs );
-/* @[define_sntp_receivetimeresponse] */
-
-/**
- * @brief Converts @ref SntpStatus_t to its equivalent
- * string.
- *
- * @note The returned string MUST NOT be modified.
- *
- * @param[in] status The status to convert to a string.
- *
- * @return The string representation of the status
- * code.
- */
-/* @[define_sntp_statustostr] */
-const char * Sntp_StatusToStr( SntpStatus_t status );
-/* @[define_sntp_statustostr] */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_SNTP_CLIENT_H_ */
diff --git a/project/coreMQTT/coreSNTP/core_sntp_config.h b/project/coreMQTT/coreSNTP/core_sntp_config.h
deleted file mode 120000
index fffb314..0000000
--- a/project/coreMQTT/coreSNTP/core_sntp_config.h
+++ /dev/null
@@ -1 +0,0 @@
-core_sntp_config_defaults.h
\ No newline at end of file
diff --git a/project/coreMQTT/coreSNTP/core_sntp_config_defaults.h b/project/coreMQTT/coreSNTP/core_sntp_config_defaults.h
deleted file mode 100644
index 162a966..0000000
--- a/project/coreMQTT/coreSNTP/core_sntp_config_defaults.h
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * coreSNTP v1.2.0
- * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_sntp_config_defaults.h
- * @brief This file represents the default values for the configuration macros
- * of the coreSNTP library.
- *
- * @note This file SHOULD NOT be modified. If custom values are needed for
- * any configuration macro, a core_sntp_config.h file should be provided to
- * the SNTP library to override the default values defined in this file.
- * To build the library with the core_sntp_config.h file, make sure to
- * not set the SNTP_DO_NOT_USE_CUSTOM_CONFIG preprocessor macro.
- */
-
-#ifndef CORE_SNTP_CONFIG_DEFAULTS_H_
-#define CORE_SNTP_CONFIG_DEFAULTS_H_
-
-/* The macro definition for SNTP_DO_NOT_USE_CUSTOM_CONFIG is for Doxygen
- * documentation only. */
-
-/**
- * @brief Define this macro to build the SNTP library without the custom config
- * file core_sntp_config.h.
- *
- * Without the custom config, the SNTP library builds with
- * default values of config macros defined in core_sntp_config_defaults.h file.
- *
- * If a custom config is provided, then SNTP_DO_NOT_USE_CUSTOM_CONFIG should not
- * be defined.
- */
-#ifdef DOXYGEN
- #define SNTP_DO_NOT_USE_CUSTOM_CONFIG
-#endif
-
-/* SNTP_DO_NOT_USE_CUSTOM_CONFIG allows building the SNTP library
- * without a custom config. If a custom config is provided, the
- * SNTP_DO_NOT_USE_CUSTOM_CONFIG macro should not be defined. */
-#ifndef SNTP_DO_NOT_USE_CUSTOM_CONFIG
- #include "core_sntp_config.h"
-#endif
-
-/**
- * @brief Macro that is called in the SNTP library for logging "Error" level
- * messages.
- *
- * To enable error level logging in the SNTP library, this macro should be mapped to the
- * application-specific logging implementation that supports error logging.
- *
- * @note This logging macro is called in the SNTP library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_sntp_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C).
- *
- * <b>Default value</b>: Error logging is turned off, and no code is generated for calls
- * to the macro in the SNTP library on compilation.
- */
-#ifndef LogError
- #define LogError( message )
-#endif
-
-/**
- * @brief Macro that is called in the SNTP library for logging "Warning" level
- * messages.
- *
- * To enable warning level logging in the SNTP library, this macro should be mapped to the
- * application-specific logging implementation that supports warning logging.
- *
- * @note This logging macro is called in the SNTP library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_sntp_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/).
- *
- * <b>Default value</b>: Warning logs are turned off, and no code is generated for calls
- * to the macro in the SNTP library on compilation.
- */
-#ifndef LogWarn
- #define LogWarn( message )
-#endif
-
-/**
- * @brief Macro that is called in the SNTP library for logging "Info" level
- * messages.
- *
- * To enable info level logging in the SNTP library, this macro should be mapped to the
- * application-specific logging implementation that supports info logging.
- *
- * @note This logging macro is called in the SNTP library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_sntp_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/).
- *
- * <b>Default value</b>: Info logging is turned off, and no code is generated for calls
- * to the macro in the SNTP library on compilation.
- */
-#ifndef LogInfo
- #define LogInfo( message )
-#endif
-
-/**
- * @brief Macro that is called in the SNTP library for logging "Debug" level
- * messages.
- *
- * To enable debug level logging from SNTP library, this macro should be mapped to the
- * application-specific logging implementation that supports debug logging.
- *
- * @note This logging macro is called in the SNTP library with parameters wrapped in
- * double parentheses to be ISO C89/C90 standard compliant. For a reference
- * POSIX implementation of the logging macros, refer to core_sntp_config.h files, and the
- * logging-stack in demos folder of the
- * [AWS IoT Embedded C SDK repository](https://github.com/aws/aws-iot-device-sdk-embedded-C/).
- *
- * <b>Default value</b>: Debug logging is turned off, and no code is generated for calls
- * to the macro in the SNTP library on compilation.
- */
-#ifndef LogDebug
- #define LogDebug( message )
-#endif
-
-#endif /* ifndef CORE_SNTP_CONFIG_DEFAULTS_H_ */
diff --git a/project/coreMQTT/coreSNTP/core_sntp_serializer.c b/project/coreMQTT/coreSNTP/core_sntp_serializer.c
deleted file mode 100644
index 14fffed..0000000
--- a/project/coreMQTT/coreSNTP/core_sntp_serializer.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/*
- * coreSNTP v1.2.0
- * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_sntp_serializer.c
- * @brief Implementation of the Serializer API of the coreSNTP library.
- */
-
-/* Standard includes. */
-#include <string.h>
-#include <stdbool.h>
-#include <assert.h>
-
-/* Include API header. */
-#include "core_sntp_serializer.h"
-
-#include "core_sntp_config_defaults.h"
-
-/**
- * @brief The version of SNTP supported by the coreSNTP library by complying
- * with the SNTPv4 specification defined in [RFC 4330](https://tools.ietf.org/html/rfc4330).
- */
-#define SNTP_VERSION ( 4U )
-
-/**
- * @brief The bit mask for the "Mode" information in the first byte of an SNTP packet.
- * The "Mode" field occupies bits 0-2 of the byte.
- * @note Refer to the [RFC 4330 Section 4](https://tools.ietf.org/html/rfc4330#section-4)
- * for more information.
- */
-#define SNTP_MODE_BITS_MASK ( 0x07U )
-
-/**
- * @brief The value indicating a "client" in the "Mode" field of an SNTP packet.
- * @note Refer to the [RFC 4330 Section 4](https://tools.ietf.org/html/rfc4330#section-4)
- * for more information.
- */
-#define SNTP_MODE_CLIENT ( 3U )
-
-/**
- * @brief The value indicating a "server" in the "Mode" field of an SNTP packet.
- * @note Refer to the [RFC 4330 Section 4](https://tools.ietf.org/html/rfc4330#section-4)
- * for more information.
- */
-#define SNTP_MODE_SERVER ( 4U )
-
-/**
- * @brief The position of the least significant bit of the "Leap Indicator" field
- * in first byte of an SNTP packet. The "Leap Indicator" field occupies bits 6-7 of the byte.
- * @note Refer to the [RFC 4330 Section 4](https://tools.ietf.org/html/rfc4330#section-4)
- * for more information.
- */
-#define SNTP_LEAP_INDICATOR_LSB_POSITION ( 6 )
-
-/**
- * @brief Value of Stratum field in SNTP packet representing a Kiss-o'-Death message
- * from server.
- */
-#define SNTP_KISS_OF_DEATH_STRATUM ( 0U )
-
-/**
- * @brief The position of least significant bit of the "Version" information
- * in the first byte of an SNTP packet. "Version" field occupies bits 3-5 of
- * the byte.
- * @note Refer to the [RFC 4330 Section 4](https://tools.ietf.org/html/rfc4330#section-4)
- * for more information.
- */
-#define SNTP_VERSION_LSB_POSITION ( 3 )
-
-/**
- * @brief The integer value of the Kiss-o'-Death ASCII code, "DENY", used
- * for comparison with data in an SNTP response.
- * @note Refer to [RFC 4330 Section 8](https://tools.ietf.org/html/rfc4330#section-8)
- * for more information.
- */
-#define KOD_CODE_DENY_UINT_VALUE ( 0x44454e59U )
-
-/**
- * @brief The integer value of the Kiss-o'-Death ASCII code, "RSTR", used
- * for comparison with data in an SNTP response.
- * @note Refer to [RFC 4330 Section 8](https://tools.ietf.org/html/rfc4330#section-8)
- * for more information.
- */
-#define KOD_CODE_RSTR_UINT_VALUE ( 0x52535452U )
-
-/**
- * @brief The integer value of the Kiss-o'-Death ASCII code, "RATE", used
- * for comparison with data in an SNTP response.
- * @note Refer to [RFC 4330 Section 8](https://tools.ietf.org/html/rfc4330#section-8)
- * for more information.
- */
-#define KOD_CODE_RATE_UINT_VALUE ( 0x52415445U )
-
-/**
- * @brief Macro to represent exactly half of the total number of seconds in an NTP era.
- * As 32 bits are used to represent the "seconds" part of an SNTP timestamp, the half of
- * the total range of seconds in an NTP era is 2^31 seconds, which represents ~68 years.
- *
- * @note This macro represents the edge case of calculating the client system clock-offset
- * relative to server time as the library ASSUMES that the client and server times are within
- * 2^31 seconds apart in duration. This is done to support calculating clock-offset for the
- * cases when server and client systems are in adjacent NTP eras, which can occur when NTP time
- * wraps around in 2036, and the relative NTP era presence of client and server times is
- * determined based on comparing first order difference values between all possible NTP era
- * configurations of the systems.
- */
-#define CLOCK_OFFSET_MAX_TIME_DIFFERENCE ( ( ( ( int64_t ) INT32_MAX + 1 ) * 1000 ) )
-
-/**
- * @brief Macro to represent the total number of milliseconds that are represented in an
- * NTP era period. This macro represents a duration of ~136 years.
- *
- * @note Rationale for calculation: The "seconds" part of an NTP timestamp is represented in
- * unsigned 32 bit width, thus, the total range of seconds it represents is 2^32,
- * i.e. (UINT32_MAX + 1).
- */
-#define TOTAL_MILLISECONDS_IN_NTP_ERA ( ( ( int64_t ) UINT32_MAX + 1 ) * 1000 )
-
-/**
- * @brief Structure representing an SNTP packet header.
- * For more information on SNTP packet format, refer to
- * [RFC 4330 Section 4](https://tools.ietf.org/html/rfc4330#section-4).
- *
- * @note This does not include extension fields for authentication data
- * for secure SNTP communication. Authentication data follows the
- * packet header represented by this structure.
- */
-typedef struct SntpPacket
-{
- /**
- * @brief Bits 6-7 leap indicator, bits 3-5 are version number, bits 0-2 are mode
- */
- uint8_t leapVersionMode;
-
- /**
- * @brief stratum
- */
- uint8_t stratum;
-
- /**
- * @brief poll interval
- */
- uint8_t poll;
-
- /**
- * @brief precision
- */
- uint8_t precision;
-
- /**
- * @brief root delay
- */
- uint32_t rootDelay;
-
- /**
- * @brief root dispersion
- */
- uint32_t rootDispersion;
-
- /**
- * @brief reference ID
- */
- uint32_t refId;
-
- /**
- * @brief reference time
- */
- SntpTimestamp_t refTime;
-
- /**
- * @brief origin timestamp
- */
- SntpTimestamp_t originTime;
-
- /**
- * @brief receive timestamp
- */
- SntpTimestamp_t receiveTime;
-
- /**
- * @brief transmit timestamp
- */
- SntpTimestamp_t transmitTime;
-} SntpPacket_t;
-
-/**
- * @brief Utility macro to fill 32-bit integer in word-sized
- * memory in network byte (or Big Endian) order.
- *
- * @param[out] pWordMemory Pointer to the word-sized memory in which
- * the 32-bit integer will be filled.
- * @param[in] data The 32-bit integer to fill in the @p wordMemory
- * in network byte order.
- *
- * @note This utility ensures that data is filled in memory
- * in expected network byte order, as an assignment operation
- * (like *pWordMemory = word) can cause undesired side-effect
- * of network-byte ordering getting reversed on Little Endian platforms.
- */
-static void fillWordMemoryInNetworkOrder( uint32_t * pWordMemory,
- uint32_t data )
-{
- assert( pWordMemory != NULL );
-
- *( ( uint8_t * ) pWordMemory ) = ( uint8_t ) ( data >> 24 );
- *( ( uint8_t * ) pWordMemory + 1 ) = ( uint8_t ) ( ( data >> 16 ) & 0x000000FFU );
- *( ( uint8_t * ) pWordMemory + 2 ) = ( uint8_t ) ( ( data >> 8 ) & 0x000000FFU );
- *( ( uint8_t * ) pWordMemory + 3 ) = ( uint8_t ) ( ( data ) & 0x000000FFU );
-}
-
-/**
- * @brief Utility macro to generate a 32-bit integer from memory containing
- * integer in network (or Big Endian) byte order.
- * @param[in] ptr Pointer to the memory containing 32-bit integer in network
- * byte order.
- *
- * @return The host representation of the 32-bit integer in the passed word
- * memory.
- */
-static uint32_t readWordFromNetworkByteOrderMemory( const uint32_t * ptr )
-{
- const uint8_t * pMemStartByte = ( const uint8_t * ) ptr;
-
- assert( ptr != NULL );
-
- return ( uint32_t ) ( ( ( uint32_t ) *( pMemStartByte ) << 24 ) |
- ( 0x00FF0000U & ( ( uint32_t ) *( pMemStartByte + 1 ) << 16 ) ) |
- ( 0x0000FF00U & ( ( uint32_t ) *( pMemStartByte + 2 ) << 8 ) ) |
- ( ( uint32_t ) *( pMemStartByte + 3 ) ) );
-}
-
-/**
- * @brief Utility to return absolute (or positively signed) value of an signed
- * 64 bit integer.
- *
- * @param[in] value The integer to return the absolute value of.
- *
- * @return The absolute value of @p value.
- */
-static int64_t absoluteOf( int64_t value )
-{
- return ( value >= 0 ) ? value : ( ( int64_t ) 0 - value );
-}
-
-/**
- * @brief Utility to determine whether a timestamp represents a zero
- * timestamp value.
- *
- * @note This utility is used to determine whether a timestamp value is
- * invalid. According to the SNTPv4 specification, a zero timestamp value
- * is considered invalid.
- *
- * @param[in] pTime The timestamp whose value is to be inspected for
- * zero value.
- *
- * @return `true` if the timestamp is zero; otherwise `false`.
- */
-static bool isZeroTimestamp( const SntpTimestamp_t * pTime )
-{
- bool isSecondsZero = ( pTime->seconds == 0U ) ? true : false;
- bool isFractionsZero = ( pTime->fractions == 0U ) ? true : false;
-
- return( isSecondsZero && isFractionsZero );
-}
-
-/**
- * @brief Utility to convert the "fractions" part of an SNTP timestamp to milliseconds
- * duration of time.
- * @param[in] fractions The fractions value.
- *
- * @return The milliseconds equivalent of the @p fractions value.
- */
-static uint32_t fractionsToMs( uint32_t fractions )
-{
- return( fractions / ( 1000U * SNTP_FRACTION_VALUE_PER_MICROSECOND ) );
-}
-
-/**
- * @brief Utility to safely calculate difference between server and client timestamps and
- * return the difference in the resolution of milliseconds as a signed 64 bit integer.
- * The calculated value represents the effective subtraction as ( @p serverTimeSec - @p clientTimeSec ).
- *
- * @note This utility SUPPORTS the cases of server and client timestamps being in different NTP eras,
- * and ASSUMES that the server and client systems are within 68 years of each other.
- * To handle the case of different NTP eras, this function calculates difference values for all
- * possible combinations of NTP eras of server and client times (i.e. 1. both timestamps in same era,
- * 2. server timestamp one era ahead, and 3. client timestamp being one era ahead), and determines
- * the NTP era configuration by choosing the difference value of the smallest absolute value.
- *
- * @param[in] pServerTime The server timestamp.
- * @param[in] pClientTime The client timestamp.
- *
- * @return The calculated difference between server and client times as a signed 64 bit integer.
- */
-static int64_t safeTimeDifference( const SntpTimestamp_t * pServerTime,
- const SntpTimestamp_t * pClientTime )
-{
- int64_t eraAdjustedDiff = 0;
-
- /* Convert the timestamps into 64 bit signed integer values of milliseconds. */
- int64_t serverTime = ( ( int64_t ) pServerTime->seconds * 1000 ) + ( int64_t ) fractionsToMs( pServerTime->fractions );
- int64_t clientTime = ( ( int64_t ) pClientTime->seconds * 1000 ) + ( int64_t ) fractionsToMs( pClientTime->fractions );
-
- /* The difference between the 2 timestamps is calculated by determining the whether the timestamps
- * are present in the same NTP era or adjacent NTP eras (i.e. the NTP timestamp overflow case). */
-
- /* First, calculate the first order time difference assuming that server and client times
- * are in the same NTP era. */
- int64_t diffWithNoEraAdjustment = serverTime - clientTime;
-
- /* Store the absolute value of the time difference which will be used for comparison with
- * different cases of relative NTP era configuration of client and server times. */
- int64_t absSameEraDiff = absoluteOf( diffWithNoEraAdjustment );
-
- /* If the absolute difference value is 2^31 seconds, it means that the server and client times are
- * away by exactly half the range of SNTP timestamp "second" values representable in unsigned 32 bits.
- * In such a case, irrespective of whether the 2 systems exist in the same or adjacent NTP eras, the
- * time difference calculated between the systems will ALWAYS yield the same value when viewed from
- * all NTP era configurations of the times.
- * For such a case, we will ASSUME that the server time is AHEAD of client time, and thus, generate
- * a positive clock-offset value.
- */
- if( absSameEraDiff == CLOCK_OFFSET_MAX_TIME_DIFFERENCE )
- {
- /* It does not matter whether server and client are in the same era for this
- * special case as the difference value for both same and adjacent eras will yield
- * the same absolute value of 2^31.*/
- eraAdjustedDiff = CLOCK_OFFSET_MAX_TIME_DIFFERENCE;
- }
- else
- {
- /* Determine if server time belongs to an NTP era different than the client time, and accordingly
- * choose the 64 bit representation of the first order difference to account for the era.
- * The logic for determining the relative era presence of the timestamps is by calculating the
- * first order difference (of "Server Time - Client Time") for all the 3 different era combinations
- * (1. both timestamps in same era, 2. server time one era ahead, 3. client time one era ahead)
- * and choosing the NTP era configuration that has the smallest first order difference value.
- */
- int64_t diffWithServerEraAdjustment = serverTime + TOTAL_MILLISECONDS_IN_NTP_ERA -
- clientTime; /* This helps determine whether server is an
- * era ahead of client time. */
- int64_t diffWithClientEraAdjustment = serverTime -
- ( TOTAL_MILLISECONDS_IN_NTP_ERA + clientTime ); /* This helps determine whether server is an
- * era behind of client time. */
-
- /* Store the absolute value equivalents of all the time difference configurations
- * for easier comparison to smallest value from them. */
- int64_t absServerEraAheadDiff = absoluteOf( diffWithServerEraAdjustment );
- int64_t absClientEraAheadDiff = absoluteOf( diffWithClientEraAdjustment );
-
- /* Determine the correct relative era of client and server times by checking which era
- * configuration of difference value represents the least difference. */
- if( ( absSameEraDiff <= absServerEraAheadDiff ) && ( absSameEraDiff <= absClientEraAheadDiff ) )
- {
- /* Both server and client times are in the same era. */
- eraAdjustedDiff = diffWithNoEraAdjustment;
- }
- /* Check if server time is an NTP era ahead of client time. */
- else if( absServerEraAheadDiff < absSameEraDiff )
- {
- /* Server time is in NTP era 1 while client time is in NTP era 0. */
- eraAdjustedDiff = diffWithServerEraAdjustment;
- }
- /* Now, we know that the client time is an era ahead of server time. */
- else
- {
- /* Server time is in NTP era 0 while client time is in NTP era 1. */
- eraAdjustedDiff = diffWithClientEraAdjustment;
- }
- }
-
- return eraAdjustedDiff;
-}
-
-/**
- * @brief Utility to calculate clock offset of system relative to the
- * server using the on-wire protocol specified in the NTPv4 specification.
- * For more information on on-wire protocol, refer to
- * [RFC 5905 Section 8](https://tools.ietf.org/html/rfc5905#section-8).
- *
- * @note The following diagram explains the calculation of the clock
- * offset:
- *
- * T2 T3
- * --------------------------------- <----- *SNTP/NTP server*
- * /\ \
- * / \
- * Request* / \ *Response*
- * / \/
- * --------------------------------- <----- *SNTP client*
- * T1 T4
- *
- * The four most recent timestamps, T1 through T4, are used to compute
- * the clock offset of SNTP client relative to the server where:
- *
- * T1 = Client Request Transmit Time
- * T2 = Server Receive Time (of client request)
- * T3 = Server Response Transmit Time
- * T4 = Client Receive Time (of server response)
- *
- * Clock Offset = T(NTP/SNTP server) - T(SNTP client)
- * = [( T2 - T1 ) + ( T3 - T4 )]
- * ---------------------------
- * 2
- *
- * @note Both NTPv4 and SNTPv4 specifications suggest calculating the
- * clock offset value, if possible. As the timestamp format uses 64 bit
- * integer and there exist 2 orders of arithmetic calculations on the
- * timestamp values (subtraction followed by addition as shown in the
- * diagram above), the clock offset for the system can be calculated
- * ONLY if the value can be represented in 62 significant bits and 2 sign
- * bits i.e. if the system clock is within 34 years (in the future or past)
- * of the server time.
- *
- * @param[in] pClientTxTime The system time of sending the SNTP request.
- * This is the same as "T1" in the above diagram.
- * @param[in] pServerRxTime The server time of receiving the SNTP request
- * packet from the client. This is the same as "T2" in the above diagram.
- * @param[in] pServerTxTime The server time of sending the SNTP response
- * packet. This is the same as "T3" in the above diagram.
- * @param[in] pClientRxTime The system time of receiving the SNTP response
- * from the server. This is the same as "T4" in the above diagram.
- * @param[out] pClockOffset This will be filled with the calculated offset value
- * of the system clock relative to the server time with the assumption that the
- * system clock is within 68 years of server time.
- */
-static void calculateClockOffset( const SntpTimestamp_t * pClientTxTime,
- const SntpTimestamp_t * pServerRxTime,
- const SntpTimestamp_t * pServerTxTime,
- const SntpTimestamp_t * pClientRxTime,
- int64_t * pClockOffset )
-{
- /* Variable for storing the first-order difference between timestamps. */
- int64_t firstOrderDiffSend = 0;
- int64_t firstOrderDiffRecv = 0;
-
- assert( pClientTxTime != NULL );
- assert( pServerRxTime != NULL );
- assert( pServerTxTime != NULL );
- assert( pClientRxTime != NULL );
- assert( pClockOffset != NULL );
-
- /* Perform first order difference of timestamps on the network send path i.e. T2 - T1.
- * Note: The calculated difference value will always represent years in the range of
- *[-68 years, +68 years]. */
- firstOrderDiffSend = safeTimeDifference( pServerRxTime, pClientTxTime );
-
- /* Perform first order difference of timestamps on the network receive path i.e. T3 - T4.
- * Note: The calculated difference value will always represent years in the range of
- *[-68 years, +68 years]. */
- firstOrderDiffRecv = safeTimeDifference( pServerTxTime, pClientRxTime );
-
- /* Now calculate the system clock-offset relative to server time as the average of the
- * first order difference of timestamps in both directions of network path.
- * Note: This will ALWAYS represent offset in the range of [-68 years, +68 years]. */
- *pClockOffset = ( firstOrderDiffSend + firstOrderDiffRecv ) / 2;
-}
-
-/**
- * @brief Parse a SNTP response packet by determining whether it is a rejected
- * or accepted response to an SNTP request, and accordingly, populate the
- * @p pParsedResponse parameter with the parsed data.
- *
- * @note If the server has rejected the request with the a Kiss-o'-Death message,
- * then this function will set the associated rejection code in the output parameter
- * while setting the remaining members to zero.
- * If the server has accepted the time request, then the function will set the
- * rejectedResponseCode member of the output parameter to #SNTP_KISS_OF_DEATH_CODE_NONE,
- * and set the other the members with appropriate data extracted from the response
- * packet.
- *
- * @param[in] pResponsePacket The SNTP response packet from server to parse.
- * @param[in] pRequestTxTime The system time (in SNTP timestamp format) of
- * sending the SNTP request to server.
- * @param[in] pResponseRxTime The system time (in SNTP timestamp format) of
- * receiving the SNTP response from server.
- * @param[out] pParsedResponse The parameter that will be populated with data
- * parsed from the response packet, @p pResponsePacket.
- *
- * @return This function returns one of the following:
- * - #SntpSuccess if the server response does not represent a Kiss-o'-Death
- * message.
- * - #SntpRejectedResponseChangeServer if the server rejected with a code
- * indicating that client cannot be retry requests to it.
- * - #SntpRejectedResponseRetryWithBackoff if the server rejected with a code
- * indicating that client should back-off before retrying request.
- * - #SntpRejectedResponseOtherCode if the server rejected with a code
- * other than "DENY", "RSTR" and "RATE".
- */
-static SntpStatus_t parseValidSntpResponse( const SntpPacket_t * pResponsePacket,
- const SntpTimestamp_t * pRequestTxTime,
- const SntpTimestamp_t * pResponseRxTime,
- SntpResponseData_t * pParsedResponse )
-{
- SntpStatus_t status = SntpSuccess;
-
- assert( pResponsePacket != NULL );
- assert( pResponseRxTime != NULL );
- assert( pParsedResponse != NULL );
-
- /* Clear the output parameter memory to zero. */
- ( void ) memset( pParsedResponse, 0, sizeof( *pParsedResponse ) );
-
- /* Determine if the server has accepted or rejected the request for time. */
- if( pResponsePacket->stratum == SNTP_KISS_OF_DEATH_STRATUM )
- {
- /* Server has sent a Kiss-o'-Death message i.e. rejected the request. */
-
- /* Extract the kiss-code sent by the server from the "Reference ID" field
- * of the SNTP packet. */
- pParsedResponse->rejectedResponseCode =
- readWordFromNetworkByteOrderMemory( &pResponsePacket->refId );
-
- /* Determine the return code based on the Kiss-o'-Death code. */
- switch( pParsedResponse->rejectedResponseCode )
- {
- case KOD_CODE_DENY_UINT_VALUE:
- case KOD_CODE_RSTR_UINT_VALUE:
- status = SntpRejectedResponseChangeServer;
- break;
-
- case KOD_CODE_RATE_UINT_VALUE:
- status = SntpRejectedResponseRetryWithBackoff;
- break;
-
- default:
- status = SntpRejectedResponseOtherCode;
- break;
- }
- }
- else
- {
- /* Server has responded successfully to the time request. */
-
- SntpTimestamp_t serverRxTime;
-
- /* Map of integer value to SntpLeapSecondInfo_t enumeration type for the
- * "Leap Indicator" field in the first byte of an SNTP packet.
- * Note: This map is used to not violate MISRA Rule 10.5 when directly
- * converting an integer to enumeration type.
- */
- const SntpLeapSecondInfo_t leapIndicatorTypeMap[] =
- {
- NoLeapSecond,
- LastMinuteHas61Seconds,
- LastMinuteHas59Seconds,
- AlarmServerNotSynchronized
- };
-
- /* Set the Kiss-o'-Death code value to NULL as server has responded favorably
- * to the time request. */
- pParsedResponse->rejectedResponseCode = SNTP_KISS_OF_DEATH_CODE_NONE;
-
- /* Fill the output parameter with the server time which is the
- * "transmit" time in the response packet. */
- pParsedResponse->serverTime.seconds =
- readWordFromNetworkByteOrderMemory( &pResponsePacket->transmitTime.seconds );
- pParsedResponse->serverTime.fractions =
- readWordFromNetworkByteOrderMemory( &pResponsePacket->transmitTime.fractions );
-
- /* Extract information of any upcoming leap second from the response. */
- pParsedResponse->leapSecondType = leapIndicatorTypeMap[
- ( pResponsePacket->leapVersionMode >> SNTP_LEAP_INDICATOR_LSB_POSITION ) ];
-
- /* Store the "receive" time in SNTP response packet in host order. */
- serverRxTime.seconds =
- readWordFromNetworkByteOrderMemory( &pResponsePacket->receiveTime.seconds );
- serverRxTime.fractions =
- readWordFromNetworkByteOrderMemory( &pResponsePacket->receiveTime.fractions );
-
- /* Calculate system clock offset relative to server time, if possible, within
- * the 64 bit integer width of the SNTP timestamp. */
- calculateClockOffset( pRequestTxTime,
- &serverRxTime,
- &pParsedResponse->serverTime,
- pResponseRxTime,
- &pParsedResponse->clockOffsetMs );
- }
-
- return status;
-}
-
-
-SntpStatus_t Sntp_SerializeRequest( SntpTimestamp_t * pRequestTime,
- uint32_t randomNumber,
- void * pBuffer,
- size_t bufferSize )
-{
- SntpStatus_t status = SntpSuccess;
-
- if( pRequestTime == NULL )
- {
- status = SntpErrorBadParameter;
- }
- else if( pBuffer == NULL )
- {
- status = SntpErrorBadParameter;
- }
- else if( bufferSize < SNTP_PACKET_BASE_SIZE )
- {
- status = SntpErrorBufferTooSmall;
- }
-
- /* Zero timestamps for client request time is not allowed to protect against
- * attack spoofing server response containing zero value for "originate timestamp".
- * Note: In SNTP/NTP communication, the "originate timestamp" of a valid server response
- * matches the "transmit timestamp" in corresponding client request packet. */
- else if( isZeroTimestamp( pRequestTime ) == true )
- {
- status = SntpErrorBadParameter;
- }
- else
- {
- /* MISRA Ref 11.5.1 [Void pointer assignment] */
- /* More details at: https://github.com/FreeRTOS/coreSNTP/blob/main/MISRA.md#rule-115 */
- /* coverity[misra_c_2012_rule_11_5_violation] */
- SntpPacket_t * pRequestPacket = ( SntpPacket_t * ) pBuffer;
-
- /* Fill the buffer with zero as most fields are zero for a standard SNTP
- * request packet.*/
- ( void ) memset( pBuffer, 0, sizeof( SntpPacket_t ) );
-
- /* Set the first byte of the request packet for "Version" and "Mode" fields */
- pRequestPacket->leapVersionMode = 0U /* Leap Indicator */ |
- ( SNTP_VERSION << SNTP_VERSION_LSB_POSITION ) /* Version Number */ |
- SNTP_MODE_CLIENT /* Mode */;
-
-
- /* Add passed random number to non-significant bits of the fractions part
- * of the transmit timestamp.
- * This is suggested by the SNTPv4 (and NTPv4) specification(s)
- * to protect against replay attacks. Refer to RFC 4330 Section 3 for
- * more information.
- * Adding random bits to the least significant 16 bits of the fractions
- * part of the timestamp affects only ~15 microseconds of information
- * (calculated as 0xFFFF * 232 picoseconds).
- */
- pRequestTime->fractions = ( pRequestTime->fractions
- | ( randomNumber >> 16 ) );
-
- /* Update the request buffer with request timestamp in network byte order. */
- fillWordMemoryInNetworkOrder( &pRequestPacket->transmitTime.seconds,
- pRequestTime->seconds );
- fillWordMemoryInNetworkOrder( &pRequestPacket->transmitTime.fractions,
- pRequestTime->fractions );
- }
-
- return status;
-}
-
-
-SntpStatus_t Sntp_DeserializeResponse( const SntpTimestamp_t * pRequestTime,
- const SntpTimestamp_t * pResponseRxTime,
- const void * pResponseBuffer,
- size_t bufferSize,
- SntpResponseData_t * pParsedResponse )
-{
- SntpStatus_t status = SntpSuccess;
- /* MISRA Ref 11.5.1 [Void pointer assignment] */
- /* More details at: https://github.com/FreeRTOS/coreSNTP/blob/main/MISRA.md#rule-115 */
- /* coverity[misra_c_2012_rule_11_5_violation] */
- const SntpPacket_t * pResponsePacket = ( const SntpPacket_t * ) pResponseBuffer;
-
- if( ( pRequestTime == NULL ) || ( pResponseRxTime == NULL ) ||
- ( pResponseBuffer == NULL ) || ( pParsedResponse == NULL ) )
- {
- status = SntpErrorBadParameter;
- }
- else if( bufferSize < SNTP_PACKET_BASE_SIZE )
- {
- status = SntpErrorBufferTooSmall;
- }
-
- /* Zero timestamps for client request time is not allowed to protect against
- * attack spoofing server response containing zero value for "originate timestamp".
- * Note: In SNTP/NTP communication, the "originate timestamp" of a valid server response
- * matches the "transmit timestamp" in corresponding client request packet. */
- else if( isZeroTimestamp( pRequestTime ) == true )
- {
- status = SntpErrorBadParameter;
- }
- /* Check if the packet represents a server in the "Mode" field. */
- else if( ( pResponsePacket->leapVersionMode & SNTP_MODE_BITS_MASK ) != SNTP_MODE_SERVER )
- {
- status = SntpInvalidResponse;
- }
-
- /* Check if any of the timestamps in the response packet are zero, which is invalid.
- * Note: This is done to protect against a nuanced server spoofing attack where if the
- * SNTP client resets its internal state of "Client transmit timestamp" (OR "originate
- * timestamp" from server perspective) to zero as a protection against replay attack, an
- * an attacker with this knowledge of the client operation can spoof a server response
- * containing the "originate timestamp" as zero. Thus, to protect against such attack,
- * a server response packet with any zero timestamp is rejected. */
- else if( ( isZeroTimestamp( &pResponsePacket->originTime ) == true ) ||
- ( isZeroTimestamp( &pResponsePacket->receiveTime ) == true ) ||
- ( isZeroTimestamp( &pResponsePacket->transmitTime ) == true ) )
- {
- status = SntpInvalidResponse;
- }
-
-
- /* Validate that the server has sent the client's request timestamp in the
- * "originate" timestamp field of the response. */
- else if( ( pRequestTime->seconds !=
- readWordFromNetworkByteOrderMemory( &pResponsePacket->originTime.seconds ) ) ||
- ( pRequestTime->fractions !=
- readWordFromNetworkByteOrderMemory( &pResponsePacket->originTime.fractions ) ) )
-
- {
- status = SntpInvalidResponse;
- }
- else
- {
- /* As the response packet is valid, parse more information from it and
- * populate the output parameter. */
-
- status = parseValidSntpResponse( pResponsePacket,
- pRequestTime,
- pResponseRxTime,
- pParsedResponse );
- }
-
- return status;
-}
-
-SntpStatus_t Sntp_CalculatePollInterval( uint16_t clockFreqTolerance,
- uint16_t desiredAccuracy,
- uint32_t * pPollInterval )
-{
- SntpStatus_t status = SntpSuccess;
-
- if( ( clockFreqTolerance == 0U ) || ( desiredAccuracy == 0U ) || ( pPollInterval == NULL ) )
- {
- status = SntpErrorBadParameter;
- }
- else
- {
- uint32_t exactIntervalForAccuracy = 0U;
- uint8_t log2PollInterval = 0U;
-
- /* Calculate the poll interval required for achieving the exact desired clock accuracy
- * with the following formulae:
- *
- * System Clock Drift Rate ( microseconds / second ) = Clock Frequency Tolerance (in PPM )
- * Maximum Clock Drift ( milliseconds ) = Desired Accuracy ( milliseconds )
- *
- * Poll Interval ( seconds ) = Maximum Clock Drift
- * ---------------------------
- * System Clock Drift Rate
- *
- * = Maximum Drift ( milliseconds ) * 1000 ( microseconds / millisecond )
- * ------------------------------------------------------------------------
- * System Clock Drift Rate ( microseconds / second )
- *
- * = Desired Accuracy * 1000
- * ------------------------------
- * Clock Frequency Tolerance
- */
- exactIntervalForAccuracy = ( ( uint32_t ) desiredAccuracy * 1000U ) / clockFreqTolerance;
-
- /* Check if calculated poll interval value falls in the supported range of seconds. */
- if( exactIntervalForAccuracy == 0U )
- {
- /* Poll interval value is less than 1 second, and is not supported by the function. */
- status = SntpZeroPollInterval;
- }
- else
- {
- /* To calculate the log 2 value of the exact poll interval value, first determine the highest
- * bit set in the value. */
- while( exactIntervalForAccuracy != 0U )
- {
- log2PollInterval++;
- exactIntervalForAccuracy /= 2U;
- }
-
- /* Convert the highest bit in the exact poll interval value to the nearest integer
- * value lower or equal to the log2 of the exact poll interval value. */
- log2PollInterval--;
-
- /* Calculate the poll interval as the closest exponent of 2 value that achieves
- * equal or higher accuracy than the desired accuracy. */
- *pPollInterval = ( ( ( uint32_t ) 1U ) << log2PollInterval );
- }
- }
-
- return status;
-}
-
-SntpStatus_t Sntp_ConvertToUnixTime( const SntpTimestamp_t * pSntpTime,
- uint32_t * pUnixTimeSecs,
- uint32_t * pUnixTimeMicrosecs )
-{
- SntpStatus_t status = SntpSuccess;
-
- if( ( pSntpTime == NULL ) || ( pUnixTimeSecs == NULL ) || ( pUnixTimeMicrosecs == NULL ) )
- {
- status = SntpErrorBadParameter;
- }
- /* Check if passed time does not lie in the [UNIX epoch in 1970, UNIX time overflow in 2038] time range. */
- else if( ( pSntpTime->seconds > SNTP_TIME_AT_LARGEST_UNIX_TIME_SECS ) &&
- ( pSntpTime->seconds < SNTP_TIME_AT_UNIX_EPOCH_SECS ) )
- {
- /* The SNTP timestamp is outside the supported time range for conversion. */
- status = SntpErrorTimeNotSupported;
- }
- else
- {
- /* Handle case when timestamp represents date in SNTP era 1
- * (i.e. time from 7 Feb 2036 6:28:16 UTC onwards). */
- if( pSntpTime->seconds <= SNTP_TIME_AT_LARGEST_UNIX_TIME_SECS )
- {
- /* Unix Time ( seconds ) = Seconds Duration in
- * [UNIX epoch, SNTP Era 1 Epoch Time]
- * +
- * Sntp Time since Era 1 Epoch
- */
- *pUnixTimeSecs = UNIX_TIME_SECS_AT_SNTP_ERA_1_SMALLEST_TIME + pSntpTime->seconds;
- }
- /* Handle case when SNTP timestamp is in SNTP era 1 time range. */
- else
- {
- *pUnixTimeSecs = pSntpTime->seconds - SNTP_TIME_AT_UNIX_EPOCH_SECS;
- }
-
- /* Convert SNTP fractions to microseconds for UNIX time. */
- *pUnixTimeMicrosecs = pSntpTime->fractions / SNTP_FRACTION_VALUE_PER_MICROSECOND;
- }
-
- return status;
-}
diff --git a/project/coreMQTT/coreSNTP/core_sntp_serializer.h b/project/coreMQTT/coreSNTP/core_sntp_serializer.h
deleted file mode 100644
index 55215f1..0000000
--- a/project/coreMQTT/coreSNTP/core_sntp_serializer.h
+++ /dev/null
@@ -1,535 +0,0 @@
-/*
- * coreSNTP v1.2.0
- * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * SPDX-License-Identifier: MIT
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
- * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
- * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
- * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * @file core_sntp_serializer.h
- * @brief API for serializing SNTP request packets and, and de-serializing SNTP
- * response packets.
- * This API layer adheres to the SNTPv4 specification defined in
- * [RFC 4330](https://tools.ietf.org/html/rfc4330).
- */
-
-#ifndef CORE_SNTP_SERIALIZER_H_
-#define CORE_SNTP_SERIALIZER_H_
-
-/* Standard include. */
-#include <stdint.h>
-#include <stddef.h>
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- extern "C" {
-#endif
-/* *INDENT-ON* */
-
-/**
- * @ingroup sntp_constants
- * @brief The base packet size of request and response of the (S)NTP protocol.
- * @note This is the packet size without any authentication headers for security
- * mechanism. If the application uses a security mechanism for communicating with
- * an (S)NTP server, it can add authentication data after the SNTP packet is
- * serialized with the @ref Sntp_SerializeRequest API function.
- */
-#define SNTP_PACKET_BASE_SIZE ( 48U )
-
-/**
- * @ingroup sntp_constants
- * @brief Number of SNTP timestamp fractions in 1 microsecond.
- *
- * The fraction's part of an SNTP timestamp is 32-bits wide, thereby, giving a
- * resolution of 2^(-32) seconds ~ 232 picoseconds.
- *
- * @note The application can use this value to convert microseconds part of system
- * time into SNTP timestamp fractions. For example, if the microseconds
- * part of system time is n microseconds, the fractions value to be used for the
- * SNTP timestamp part will be n * SNTP_FRACTION_VALUE_PER_MICROSECOND.
- */
-#define SNTP_FRACTION_VALUE_PER_MICROSECOND ( 4295U )
-
-/**
- * @ingroup sntp_constants
- * @brief The seconds part of SNTP time at the UNIX epoch time, which represents
- * an offset of 70 years (in seconds) between SNTP epoch and UNIX epoch time.
- * SNTP uses 1st Jan 1900 UTC as the epoch time, whereas UNIX standard uses
- * 1st Jan 1970 UTC as the epoch time, thereby, causing an offset of 70 years
- * between them.
- *
- * Difference of 70 years = ((70 * 365) + 17 leap days) * 24 * 3600 seconds
- *
- * @note If your system follows UNIX time, the application can use this value to
- * convert seconds part of a system time to seconds part of the equivalent SNTP
- * time. For example, if the seconds part of system time is n seconds, the seconds
- * value to be used for the SNTP timestamp will be n + SNTP_TO_UNIX_OFFSET_SECS.
- */
-#define SNTP_TIME_AT_UNIX_EPOCH_SECS ( 2208988800U )
-
-/**
- * @ingroup sntp_constants
- * @brief The seconds value of SNTP timestamp for the largest UNIX time when
- * using signed 32-bit integer for seconds.
- * The largest time representable with a 32-bit signed integer in UNIX time
- * is 19 Jan 2038 3h 14m 7s UTC. However, as the SNTP time overflows at
- * 7 Feb 2036 6h 28m 16s UTC, therefore, the SNTP time for the largest UNIX time
- * represents the time duration between the 2 timestamps.
- *
- * SNTP Time at Largest Time Duration in the range
- * Signed 32-bit UNIX time = [7 Feb 2036 6:28:16, 19 Jan 2038 3:14:07]
- */
-#define SNTP_TIME_AT_LARGEST_UNIX_TIME_SECS ( 61505151U )
-
-/**
- * @ingroup sntp_constants
- * @brief The UNIX time (in seconds) at the smallest SNTP time in era 1,
- * i.e. UNIX time at 7 Feb 2036 6:28:16 UTC/
- *
- * Time Duration = 7 Feb 6:28:16 UTC (SNTP Era 1 Epoch) -
- * 1 Jan 1970 0:0:0 UTC (UNIX epoch)
- * = 66 years, 37 days, 6 hours, 28 minutes and 16 seconds
- * = ((66 * 365) + 16 leap days) * 24 * 3600) + (6 * 3600)
- * + (28 * 60) + 16
- */
-#define UNIX_TIME_SECS_AT_SNTP_ERA_1_SMALLEST_TIME ( 2085978496U )
-
-/**
- * @ingroup sntp_constants
- * @brief The fixed-length of any Kiss-o'-Death message ASCII code sent
- * in an SNTP server response.
- * @note An SNTP server sends a Kiss-o'-Death message to reject a time request
- * from the client. For more information on the Kiss-o'-Death codes, refer to the
- * [SNTPv4 specification Section 8](https://tools.ietf.org/html/rfc4330#section-8).
- */
-#define SNTP_KISS_OF_DEATH_CODE_LENGTH ( 4U )
-
-/**
- * @ingroup sntp_constants
- * @brief The value for the #SntpResponseData_t.rejectedResponseCode member
- * when that the server response packet does not contain a Kiss-o'-Death
- * message, and therefore, does not have a "kiss code".
- * The server sends a "kiss-code" only when it rejects an SNTP request
- * with a Kiss-o'-Death message.
- */
-#define SNTP_KISS_OF_DEATH_CODE_NONE ( 0U )
-
-/**
- * @ingroup sntp_enum_types
- * @brief Enumeration of status codes that can be returned
- * by the coreSNTP Library API.
- */
-typedef enum SntpStatus
-{
- /**
- * @brief Successful operation of an SNTP API.
- */
- SntpSuccess,
-
- /**
- * @brief Invalid parameter passed to an API function.
- */
- SntpErrorBadParameter,
-
- /**
- * @brief Server sent a Kiss-o'-Death message to reject the request for time.
- * This status can be returned by the @ref Sntp_ReceiveTimeResponse API.
- */
- SntpRejectedResponse,
-
- /**
- * @brief Server sent a Kiss-o'-Death message with non-retryable code (i.e. DENY or RSTR).
- */
- SntpRejectedResponseChangeServer,
-
- /**
- * @brief Server sent a Kiss-o'-Death message with a RATE code, which means that
- * client should back-off before retrying.
- */
- SntpRejectedResponseRetryWithBackoff,
-
- /**
- * @brief Server sent a Kiss-o'-Death message with a code, specific to the server.
- * Application can inspect the ASCII kiss-code from @ref Sntp_DeserializeResponse API.
- */
- SntpRejectedResponseOtherCode,
-
- /**
- * @brief Application provided insufficient buffer space for serializing
- * or de-serializing an SNTP packet.
- * The minimum size of an SNTP packet is #SNTP_PACKET_BASE_SIZE
- * bytes. */
- SntpErrorBufferTooSmall,
-
- /**
- * @brief Server response failed validation checks for expected data in SNTP packet.
- */
- SntpInvalidResponse,
-
- /**
- * @brief Poll interval value is under 1 second which cannot be calculated
- * by @ref Sntp_CalculatePollInterval.
- */
- SntpZeroPollInterval,
-
- /**
- * @brief SNTP timestamp cannot be converted to UNIX time as time does not lie
- * in time range supported by Sntp_ConvertToUnixTime.
- */
- SntpErrorTimeNotSupported,
-
- /**
- * @brief The user-defined DNS resolution interface, @ref SntpResolveDns_t, failed to resolve
- * address for a time server. This status is returned by the @ref Sntp_SendTimeRequest API.
- */
- SntpErrorDnsFailure,
-
- /**
- * @brief Networking operation of sending or receiving SNTP packet through the user-defined UDP
- * transport interface, @ref UdpTransportInterface_t, failed.
- * This status is returned by either of @ref Sntp_SendTimeRequest OR @ref Sntp_ReceiveTimeResponse
- * APIs.
- */
- SntpErrorNetworkFailure,
-
- /**
- * @brief Time server is not authenticated from the authentication data in its response.
- * This status can be returned by the user-supplied definition of the
- * @ref SntpValidateServerAuth_t authentication interface.
- */
- SntpServerNotAuthenticated,
-
- /**
- * @brief Failure from the user-supplied authentication interface, @ref SntpAuthenticationInterface_t,
- * in either generating authentication data for SNTP request OR validating the authentication
- * data in SNTP response from server.
- */
- SntpErrorAuthFailure,
-
- /**
- * @brief A timeout occurred in sending time request packet over the network to a server through the
- * @ref Sntp_SendTimeRequest API.
- */
- SntpErrorSendTimeout,
-
- /**
- * @brief A timeout has occurred in receiving server response with the @ref Sntp_ReceiveTimeResponse
- * API.
- */
- SntpErrorResponseTimeout,
-
- /**
- * @brief No SNTP packet for server response is received from the network by the
- * @ref Sntp_ReceiveTimeResponse API.
- */
- SntpNoResponseReceived,
-
- /**
- * @brief The SNTP context passed to @ref Sntp_SendTimeRequest or @ref Sntp_ReceiveTimeResponse APIs is
- * is uninitialized.
- */
- SntpErrorContextNotInitialized
-} SntpStatus_t;
-
-/**
- * @ingroup sntp_enum_types
- * @brief Enumeration for leap second information that an SNTP server can
- * send its response to a time request. An SNTP server sends information about
- * whether there is an upcoming leap second adjustment in the last day of the
- * current month.
- *
- * @note A leap second is an adjustment made in atomic clock time because Earth's rotation
- * can be inconsistent. Leap seconds are usually incorporated as an extra second insertion
- * or second deletion in the last minute before midnight i.e. in the minute of 23h:59m UTC
- * on the last day of June or December. For more information on leap seconds, refer to
- * https://www.nist.gov/pml/time-and-frequency-division/leap-seconds-faqs.
- */
-typedef enum SntpLeapSecondInfo
-{
- NoLeapSecond = 0x00, /** <@brief There is no upcoming leap second adjustment. */
- LastMinuteHas61Seconds = 0x01, /** <@brief A leap second should be inserted in the last minute before midnight. */
- LastMinuteHas59Seconds = 0x02, /** <@brief A leap second should be deleted from the last minute before midnight. */
- AlarmServerNotSynchronized = 0x03 /** <@brief An alarm condition meaning that server's time is not synchronized
- * to an upstream NTP (or SNTP) server. */
-} SntpLeapSecondInfo_t;
-
-/**
- * @ingroup sntp_struct_types
- * @brief Structure representing an SNTP timestamp.
- *
- * @note The SNTP timestamp uses 1st January 1900 0h 0m 0s Coordinated Universal Time (UTC)
- * as the primary epoch i.e. the timestamp represents current time as the amount of time since
- * the epoch time.
- * Refer to the [SNTPv4 specification](https://tools.ietf.org/html/rfc4330#section-3) for more
- * information of the SNTP timestamp format.
- */
-typedef struct SntpTimestamp
-{
- uint32_t seconds; /**< @brief Number of seconds since epoch time. */
- uint32_t fractions; /**< @brief The fractions part of the SNTP timestamp with resolution
- * of 2^(-32) ~ 232 picoseconds. */
-} SntpTimestamp_t;
-
-/**
- * @ingroup sntp_struct_types
- * @brief Structure representing data parsed from an SNTP response from server
- * as well as data of arithmetic calculations derived from the response.
- */
-typedef struct SntpResponse
-{
- /**
- * @brief The timestamp sent by the server.
- */
- SntpTimestamp_t serverTime;
-
- /**
- * @brief The information of an upcoming leap second in the
- * server response.
- */
- SntpLeapSecondInfo_t leapSecondType;
-
- /**
- * @brief If a server responded with Kiss-o'-Death message to reject
- * time request, this is the fixed length ASCII code sequence for the
- * rejection.
- *
- * The Kiss-o'-Death code is always #SNTP_KISS_OF_DEATH_CODE_LENGTH
- * bytes long.
- *
- * @note If the server does not send a Kiss-o'-Death message in its
- * response, this value will be #SNTP_KISS_OF_DEATH_CODE_NONE.
- */
- uint32_t rejectedResponseCode;
-
- /**
- * @brief The offset (in milliseconds) of the system clock relative to the server time
- * calculated from timestamps in the client SNTP request and server SNTP response packets.
- * If the the system time is BEHIND the server time, then the clock-offset value is > 0.
- * If the system time is AHEAD of the server time, then the clock-offset value is < 0.
- *
- * @note This information can be used to synchronize the system clock with a "slew",
- * "step" OR combination of the two clock correction methodologies depending on the degree
- * of system clock drift (represented by the clock-offset) and the application's
- * tolerance for system clock error.
- *
- * @note The library calculates the clock-offset value using the On-Wire
- * protocol suggested by the NTPv4 specification. For more information,
- * refer to https://tools.ietf.org/html/rfc5905#section-8.
- *
- * @note The library ASSUMES that the server and client systems are within
- * ~68 years of each other clock, whether in the same NTP era or across adjacent
- * NTP eras. Thus, the client and system times MUST be within ~68 years (or
- * 2^31 seconds exactly) of each other for correct calculation of clock-offset.
- *
- * @note When the server and client times are exactly 2^31 (or INT32_MAX + 1 )
- * seconds apart, the library ASSUMES that the server time is ahead of the client
- * time, and return the clock-offset value of INT32_MAX.
- */
- int64_t clockOffsetMs;
-} SntpResponseData_t;
-
-
-/**
- * @brief Serializes an SNTP request packet to use for querying a
- * time server.
- *
- * This function will fill only #SNTP_PACKET_BASE_SIZE bytes of data in the
- * passed buffer.
- *
- * @param[in, out] pRequestTime The current time of the system, expressed as time
- * since the SNTP epoch (i.e. 0h of 1st Jan 1900 ). This time will be serialized
- * in the SNTP request packet. The function will use this parameter to return the
- * timestamp serialized in the SNTP request. To protect against attacks spoofing
- * server responses, the timestamp MUST NOT be zero in value.
- * @param[in] randomNumber A random number (generated by a True Random Generator)
- * for use in the SNTP request packet to protect against replay attacks as suggested
- * by SNTPv4 specification. For more information, refer to
- * [RFC 4330 Section 3](https://tools.ietf.org/html/rfc4330#section-3).
- * @param[out] pBuffer The buffer that will be populated with the serialized
- * SNTP request packet.
- * @param[in] bufferSize The size of the @p pBuffer buffer. It should be at least
- * #SNTP_PACKET_BASE_SIZE bytes in size.
- *
- * @note It is recommended to use a True Random Generator (TRNG) to generate
- * the random number.
- * @note The application MUST save the @p pRequestTime value for de-serializing
- * the server response with @ref Sntp_DeserializeResponse API.
- *
- * @return This function returns one of the following:
- * - #SntpSuccess when serialization operation is successful.
- * - #SntpErrorBadParameter if an invalid parameter is passed.
- * - #SntpErrorBufferTooSmall if the buffer does not have the minimum size
- * for serializing an SNTP request packet.
- */
-/* @[define_sntp_serializerequest] */
-SntpStatus_t Sntp_SerializeRequest( SntpTimestamp_t * pRequestTime,
- uint32_t randomNumber,
- void * pBuffer,
- size_t bufferSize );
-/* @[define_sntp_serializerequest] */
-
-/**
- * @brief De-serializes an SNTP packet received from a server as a response
- * to a SNTP request.
- *
- * This function will parse only the #SNTP_PACKET_BASE_SIZE bytes of data
- * in the passed buffer.
- *
- * @note If the server has sent a Kiss-o'-Death message to reject the associated
- * time request, the API function will return the appropriate return code and,
- * also, provide the ASCII code (of fixed length, #SNTP_KISS_OF_DEATH_CODE_LENGTH bytes)
- * in the #SntpResponseData_t.rejectedResponseCode member of @p pParsedResponse parameter,
- * parsed from the response packet.
- * The application SHOULD respect the server rejection and take appropriate action
- * based on the rejection code.
- * If the server response represents an accepted SNTP client request, then the API
- * function will set the #SntpResponseData_t.rejectedResponseCode member of
- * @p pParsedResponse parameter to #SNTP_KISS_OF_DEATH_CODE_NONE.
- *
- * @note If the server has positively responded with its clock time, then this API
- * function will calculate the clock-offset. For the clock-offset to be correctly
- * calculated, the system clock MUST be within ~68 years (or 2^31 seconds) of the server
- * time mentioned. This function supports clock-offset calculation when server and client
- * timestamps are in adjacent NTP eras, with one system is in NTP era 0 (i.e. before 7 Feb 2036
- * 6h:28m:14s UTC) and another system in NTP era 1 (on or after 7 Feb 2036 6h:28m:14s UTC).
- *
- * @note In the special case when the server and client times are exactly 2^31 seconds apart,
- * the library ASSUMES that the server time is ahead of the client time, and returns the
- * positive clock-offset value of INT32_MAX seconds.
- *
- * @param[in] pRequestTime The system time used in the SNTP request packet
- * that is associated with the server response. This MUST be the same as the
- * time returned by the @ref Sntp_SerializeRequest API. To protect against attacks
- * spoofing server responses, this timestamp MUST NOT be zero in value.
- * @param[in] pResponseRxTime The time of the system, expressed as time since the
- * SNTP epoch (i.e. 0h of 1st Jan 1900 ), at receiving SNTP response from server.
- * This time will be used to calculate system clock offset relative to server.
- * @param[in] pResponseBuffer The buffer containing the SNTP response from the
- * server.
- * @param[in] bufferSize The size of the @p pResponseBuffer containing the SNTP
- * response. It MUST be at least #SNTP_PACKET_BASE_SIZE bytes
- * long for a valid SNTP response.
- * @param[out] pParsedResponse The information parsed from the SNTP response packet.
- * If possible to calculate without overflow, it also contains the system clock
- * offset relative to the server time.
- *
- * @return This function returns one of the following:
- * - #SntpSuccess if the de-serialization operation is successful.
- * - #SntpErrorBadParameter if an invalid parameter is passed.
- * - #SntpErrorBufferTooSmall if the buffer does not have the minimum size
- * required for a valid SNTP response packet.
- * - #SntpInvalidResponse if the response fails sanity checks expected in an
- * SNTP response.
- * - #SntpRejectedResponseChangeServer if the server rejected with a code
- * indicating that client cannot be retry requests to it.
- * - #SntpRejectedResponseRetryWithBackoff if the server rejected with a code
- * indicating that client should back-off before retrying request.
- * - #SntpRejectedResponseOtherCode if the server rejected with a code that
- * application can inspect in the @p pParsedResponse parameter.
- */
-/* @[define_sntp_deserializeresponse] */
-SntpStatus_t Sntp_DeserializeResponse( const SntpTimestamp_t * pRequestTime,
- const SntpTimestamp_t * pResponseRxTime,
- const void * pResponseBuffer,
- size_t bufferSize,
- SntpResponseData_t * pParsedResponse );
-/* @[define_sntp_deserializeresponse] */
-
-/**
- * @brief Utility to calculate the poll interval of sending periodic time queries
- * to servers to achieve a desired system clock accuracy for a given
- * frequency tolerance of the system clock.
- *
- * For example, from the SNTPv4 specification, "if the frequency tolerance
- * is 200 parts per million (PPM) and the required accuracy is one minute,
- * the maximum timeout is about 3.5 days". In this example, the system
- * clock frequency tolerance is 200 PPM and the desired accuracy is
- * 60000 milliseconds (or 1 minute) for which this API function
- * will return the maximum poll interval value as 2^18 seconds (or ~3 days).
- *
- * @note The poll interval returned is a power of 2, which is the
- * standard way to represent the value. According to the SNTPv4 specification
- * Best Practices, an SNTP client SHOULD NOT have a poll interval less than 15 seconds.
- * https://tools.ietf.org/html/rfc4330#section-10. This API function DOES NOT
- * support poll interval calculation less than 1 second.
- *
- * @param[in] clockFreqTolerance The frequency tolerance of system clock
- * in parts per million (PPM) units. This parameter MUST be non-zero.
- * @param[in] desiredAccuracy The acceptable maximum drift, in milliseconds,
- * for the system clock. The maximum value (0xFFFF) represents ~1 minute of
- * desired clock accuracy. This parameter MUST be non-zero.
- * @param[out] pPollInterval This is filled with the poll interval, in seconds
- * calculated as the closest power of 2 value that will achieve either the
- * exact desired or higher clock accuracy @p desiredAccuracy, for the given clock
- * frequency tolerance, @p clockFreqTolerance.
- *
- * @return Returns one of the following:
- * - #SntpSuccess if calculation is successful.
- * - #SntpErrorBadParameter for an invalid parameter passed to the function.
- * - #SntpZeroPollInterval if calculated poll interval is less than 1 second.
- */
-/* @[define_sntp_calculatepollinterval] */
-SntpStatus_t Sntp_CalculatePollInterval( uint16_t clockFreqTolerance,
- uint16_t desiredAccuracy,
- uint32_t * pPollInterval );
-/* @[define_sntp_calculatepollinterval] */
-
-
-/**
- * @brief Utility to convert SNTP timestamp (that uses 1st Jan 1900 as the epoch) to
- * UNIX timestamp (that uses 1st Jan 1970 as the epoch).
- *
- * @note This function can ONLY handle conversions of SNTP timestamps that lie in the
- * range from 1st Jan 1970 0h 0m 0s, the UNIX epoch time, to 19th Jan 2038 3h 14m 7s,
- * the maximum UNIX time that can be represented in a signed 32 bit integer. (The
- * limitation is to support systems that use signed 32-bit integer to represent the
- * seconds part of the UNIX time.)
- *
- * @note This function supports overflow of the SNTP timestamp (from the 7 Feb 2036
- * 6h 28m 16s time, i.e. SNTP era 1) by treating the timestamps with seconds part
- * in the range [0, 61,505,152] seconds where the upper limit represents the UNIX
- * overflow time (i.e. 19 Jan 2038 3h 14m 7s) for systems that use signed 32-bit
- * integer to represent time.
- *
- * @param[in] pSntpTime The SNTP timestamp to convert to UNIX time.
- * @param[out] pUnixTimeSecs This will be filled with the seconds part of the
- * UNIX time equivalent of the SNTP time, @p pSntpTime.
- * @param[out] pUnixTimeMicrosecs This will be filled with the microseconds part
- * of the UNIX time equivalent of the SNTP time, @p pSntpTime.
- *
- * @return Returns one of the following:
- * - #SntpSuccess if conversion to UNIX time is successful
- * - #SntpErrorBadParameter if any of the passed parameters are NULL.
- * - #SntpErrorTimeNotSupported if the passed SNTP time does not lie in the
- * supported time range.
- */
-/* @[define_sntp_converttounixtime] */
-SntpStatus_t Sntp_ConvertToUnixTime( const SntpTimestamp_t * pSntpTime,
- uint32_t * pUnixTimeSecs,
- uint32_t * pUnixTimeMicrosecs );
-/* @[define_sntp_converttounixtime] */
-
-/* *INDENT-OFF* */
-#ifdef __cplusplus
- }
-#endif
-/* *INDENT-ON* */
-
-#endif /* ifndef CORE_SNTP_SERIALIZER_H_ */
diff --git a/project/coreMQTT/coreSNTP/makefile b/project/coreMQTT/coreSNTP/makefile
deleted file mode 100644
index b6ece0e..0000000
--- a/project/coreMQTT/coreSNTP/makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#********************************************************************************
-# Copyright: (C) 2023 LingYun IoT System Studio
-# All rights reserved.
-#
-# Filename: Makefile
-# Description: This file used compile all the source code to static library
-#
-# Version: 1.0.0(11/08/23)
-# Author: Guo Wenxue <guowenxue@gmail.com>
-# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
-#
-#*******************************************************************************
-
-PWD=$(shell pwd )
-
-BUILD_ARCH=$(shell uname -m)
-ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
- CROSS_COMPILE?=arm-linux-gnueabihf-
-endif
-
-LIBNAME=$(shell basename ${PWD} )
-TOPDIR=$(shell dirname ${PWD} )
-CFLAGS+=-D_GNU_SOURCE
-
-all: clean
- @rm -f *.o
- @${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c
- ${CROSS_COMPILE}ar -rcs lib${LIBNAME}.a *.o
-
-clean:
- @rm -f *.o
- @rm -f *.a
-
-distclean:
- @make clean
diff --git a/project/coreMQTT/etc/mqttd.conf b/project/coreMQTT/etc/mqttd.conf
deleted file mode 100644
index 50fcffa..0000000
--- a/project/coreMQTT/etc/mqttd.conf
+++ /dev/null
@@ -1,69 +0,0 @@
-[common]
-devid="RPi3B#01"
-
-# 树莓派连接的外设信息,0:禁用或未连接 其他: 使能或相关硬件连接的Pin管脚(wPI模式)
-[hardware]
-
-# 是否使能继电器模块,0:禁用 1:使能
-relay=1
-
-# 是否使能 PWM 蜂鸣器模块,0:禁用 N:Beep 次数
-beep=3
-
-# 是否使能 RGB 三色灯模块,0:禁用 1:使能
-rgbled=1
-
-# 是否使能 DS18b20 温度传感器模块,0:禁用 1:使能
-ds18b20=1
-
-# 是否使能 SHT2X 温湿度传感器模块,0:禁用 1:使能
-sht2x=1
-
-# 是否使能 TSL2561 光强传感器模块,0:禁用 1:使能
-lux=1
-
-[logger]
-
-# 日志记录文件
-file=/tmp/mqttd.log
-
-# 日志级别: 0:ERROR 1:WARN 2:INFO 3:DEBUG 4:TRACE
-level=2
-
-# 日志回滚大小
-size=1024
-
-
-[broker]
-
-# broker 服务器地址和端口号
-hostname="main.iot-yun.club"
-port=10883
-
-# broker 认证连接的用户名和密码
-username="lingyun"
-password="lingyun"
-
-# broker给subsciber和publisher发送PING报文保持 keepalive 的时间周期,单位是秒
-keepalive=30
-
-# Qos0: 发送者只发送一次消息,不进行重试,Broker不会返回确认消息。在Qos0情况下,Broker可能没有接受到消息
-# Qos1: 发送者最少发送一次消息,确保消息到达Broker,Broker需要返回确认消息PUBACK。在Qos1情况下,Broker可能接受到重复消息
-# Qos2: Qos2使用两阶段确认来保证消息的不丢失和不重复。在Qos2情况下,Broker肯定会收到消息,且只收到一次
-
-[publisher]
-
-# mosquitto_sub -h main.iot-yun.club -p 10883 -u lingyun -P lingyun -t \$Sys/Studio/Uplink
-pubTopic="$Sys/Studio/Uplink"
-pubQos=0
-
-# Publisher上报传感器数据的周期,单位是秒
-interval=60
-
-[subsciber]
-
-# mosquitto_pub -h main.iot-yun.club -p 10883 -u lingyun -P lingyun -t \$Sys/Studio/Downlink -m '{"id":"RPi3B#01", "light":"on", "buzzer":"on"}'
-# mosquitto_pub -h main.iot-yun.club -p 10883 -u lingyun -P lingyun -t \$Sys/Studio/Downlink -m '{"id":"RPi3B#01", "leds":[{"red":"on","green":"off","blue":"on"}]}'
-subTopic="$Sys/Studio/Downlink"
-subQos=0
-
diff --git a/project/coreMQTT/main.c b/project/coreMQTT/main.c
deleted file mode 100644
index 31d8fd7..0000000
--- a/project/coreMQTT/main.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2019 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: main.c
- * Description: This file
- *
- * Version: 1.0.0(29/01/19)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "29/01/19 15:34:41"
- *
- ********************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <string.h>
-#include <errno.h>
-
-#include <mosquitto.h>
-#include <cjson/cJSON.h>
-
-#include "logger.h"
-#include "util_proc.h"
-#include "modules.h"
-#include "conf.h"
-
-#define PROG_VERSION "v1.0.0"
-#define DAEMON_PIDFILE "/tmp/.mqtt.pid"
-
-void *mqtt_sub_worker(void *args);
-void *mqtt_pub_worker(void *args);
-
-static void program_usage(char *progname)
-{
-
- printf("Usage: %s [OPTION]...\n", progname);
- printf(" %s is LingYun studio MQTT daemon program running on RaspberryPi\n", progname);
-
- printf("\nMandatory arguments to long options are mandatory for short options too:\n");
- printf(" -d[debug ] Running in debug mode\n");
- printf(" -c[conf ] Specify configure file\n");
- printf(" -h[help ] Display this help information\n");
- printf(" -v[version ] Display the program version\n");
-
- printf("\n%s version %s\n", progname, PROG_VERSION);
- return;
-}
-
-int main (int argc, char **argv)
-{
- int daemon = 1;
- pthread_t tid;
- mqtt_ctx_t ctx;
- char *conf_file=NULL;
- int debug = 0;
- int opt;
- char *progname=NULL;
-
- struct option long_options[] = {
- {"conf", required_argument, NULL, 'c'},
- {"debug", no_argument, NULL, 'd'},
- {"version", no_argument, NULL, 'v'},
- {"help", no_argument, NULL, 'h'},
- {NULL, 0, NULL, 0}
- };
-
- progname = (char *)basename(argv[0]);
-
- /* Parser the command line parameters */
- while ((opt = getopt_long(argc, argv, "c:dvh", long_options, NULL)) != -1)
- {
- switch (opt)
- {
- case 'c': /* Set configure file */
- conf_file = optarg;
- break;
-
- case 'd': /* Set debug running */
- daemon = 0;
- debug = 1;
- break;
-
- case 'v': /* Get software version */
- printf("%s version %s\n", progname, PROG_VERSION);
- return 0;
-
- case 'h': /* Get help information */
- program_usage(progname);
- return 0;
-
- default:
- break;
- }
-
- }
-
- if( !conf_file )
- debug = 1;
-
- if( mqttd_parser_conf(conf_file, &ctx, debug)<0 )
- {
- fprintf(stderr, "Parser mqtted configure file failure\n");
- return -2;
- }
-
- install_default_signal();
-
- if( check_set_program_running(daemon, DAEMON_PIDFILE) < 0 )
- goto cleanup;
-
- mosquitto_lib_init();
-
- if( thread_start(&tid, mqtt_sub_worker, &ctx ) < 0 )
- {
- log_error("Start MQTT subsciber worker thread failure\n");
- goto cleanup;
- }
- log_info("Start MQTT subsciber worker thread ok\n");
-
- if( thread_start(&tid, mqtt_pub_worker, &ctx) < 0 )
- {
- log_error("Start MQTT publisher worker thread failure\n");
- goto cleanup;
- }
- log_info("Start MQTT publisher worker thread ok\n");
-
- while( ! g_signal.stop )
- {
- msleep(1000);
- }
-
-cleanup:
- mosquitto_lib_cleanup();
- log_close();
-
- return 0;
-} /* ----- End of main() ----- */
-
-void pub_connect_callback(struct mosquitto *mosq, void *userdata, int result)
-{
- mqtt_ctx_t *ctx = (mqtt_ctx_t *)userdata;
- int rv = 0;
- char msg[128];
- float temp = 0.0; /* temperature */
- float rh = 0.0; /* relative humidity */
- int retain = 0;
-
- if( result )
- {
- log_error("Publisher connect to broker server[%s:%d] failed, rv=%d\n", ctx->host, ctx->port, result);
- return ;
- }
-
- log_info("Publisher connect to broker server[%s:%d] successfully\n", ctx->host, ctx->port);
- log_debug("Publish topic '%s'\n", ctx->pubTopic);
-
- if( ctx->hwconf.ds18b20 )
- {
- memset(msg, 0, sizeof(msg));
-
- log_debug("DS18B20 temperature sensor enabled, start broadcast it\n");
-
- if( ds18b20_get_temperature(&temp) < 0 )
- snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"error\" }", ctx->devid);
- else
- snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"%.2f\" }", ctx->devid, temp);
-
- rv = mosquitto_publish(mosq, NULL, ctx->pubTopic, strlen(msg), msg, ctx->pubQos, retain);
- if( rv )
- {
- log_error("Publisher broadcast message '%s' failure: %d\n", msg, rv);
- }
- else
- {
- log_info("Publisher broadcast message '%s' ok\n", msg);
- }
- }
-
- if( ctx->hwconf.sht2x )
- {
- memset(msg, 0, sizeof(msg));
-
- log_debug("SHT2X temperature and humidity sensor enabled, start broadcast it\n");
-
- if( sht2x_get_temp_humidity(&temp, &rh) < 0 )
- snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"error\", \"RH\":\"error\" }", ctx->devid);
- else
- snprintf(msg, sizeof(msg), "{ \"id\":%s, \"temp\":\"%.2f\", \"RH\":\"%.2f\" }", ctx->devid, temp, rh);
-
- rv = mosquitto_publish(mosq, NULL, ctx->pubTopic, strlen(msg), msg, ctx->pubQos, retain);
- if( rv )
- {
- log_error("Publisher broadcast message '%s' failure: %d\n", msg, rv);
- }
- else
- {
- log_info("Publisher broadcast message '%s' ok\n", msg);
- }
- }
-
- log_info("Publisher broadcast over and disconnect broker now\n", ctx->host, ctx->port);
- mosquitto_disconnect(mosq);
-
- return ;
-}
-
-
-void *mqtt_pub_worker(void *args)
-{
- mqtt_ctx_t *ctx = (mqtt_ctx_t *)args;
- struct mosquitto *mosq;
- bool session = true;
-
-
- mosq = mosquitto_new(NULL, session, ctx);
- if( !mosq )
- {
- log_error("mosquitto_new failure\n");
- return NULL;
- }
-
- /* set connnect to broker username and password */
- if( strlen(ctx->uid)> 0 && strlen(ctx->pwd)> 0 )
- mosquitto_username_pw_set(mosq, ctx->uid, ctx->pwd);
-
- /* set callback functions */
- mosquitto_connect_callback_set(mosq, pub_connect_callback);
-
- while( !g_signal.stop )
- {
- /* connect to MQTT broker */
- if( mosquitto_connect(mosq, ctx->host, ctx->port, ctx->keepalive) )
- {
- log_error("Publisher connect to broker[%s:%d] failure: %s\n", ctx->host, ctx->port, strerror(errno));
- msleep(1000);
- continue;
- }
-
- /* -1: use default timeout 1000ms 1: unused */
- mosquitto_loop_forever(mosq, -1, 1);
-
- /* Publisher broadcast sensors data message interval time, unit seconds */
- sleep( ctx->interval );
- }
-
- mosquitto_destroy(mosq);
- return NULL;
-}
-
-void sub_connect_callback(struct mosquitto *mosq, void *userdata, int result)
-{
- mqtt_ctx_t *ctx = (mqtt_ctx_t *)userdata;
-
- if( result )
- {
- log_error("Subscriber connect to broker server failed, rv=%d\n", result);
- return ;
- }
-
- log_info("Subscriber connect to broker server[%s:%d] successfully\n", ctx->host, ctx->port);
- mosquitto_subscribe(mosq, NULL, ctx->subTopic, ctx->subQos);
-}
-
-void sub_disconnect_callback(struct mosquitto *mosq, void *userdata, int result)
-{
- mqtt_ctx_t *ctx = (mqtt_ctx_t *)userdata;
-
- log_warn("Subscriber disconnect to broker server[%s:%d], reason=%d\n", ctx->host, ctx->port, result);
-}
-
-static inline void mqtt_turn_led(int which, char *cmd)
-{
- if( strcasestr(cmd, "on") )
- turn_led(which, ON);
- else if( strcasestr(cmd, "off") )
- turn_led(which, OFF);
-}
-
-void proc_json_items(cJSON *root, mqtt_ctx_t *ctx)
-{
- int i;
- char *value;
- cJSON *item;
- cJSON *array;
- hwconf_t *hwconf = &ctx->hwconf;
-
- if( !root )
- {
- log_error("Invalid input arguments $root\n");
- return ;
- }
-
- for( i=0; i<cJSON_GetArraySize(root); i++ )
- {
- item = cJSON_GetArrayItem(root, i);
- if( !item )
- break;
-
- /* if item is cJSON_Object, then recursive call proc_json */
- if( cJSON_Object == item->type )
- {
- proc_json_items(item, ctx);
- }
- else if( cJSON_Array == item->type )
- {
- /* RGB colors led control: {"id":"RPi3B#01", "leds":[{"red":"on","green":"off","blue":"on"}]} */
- if( hwconf->led && !strcasecmp(item->string, "leds") )
- {
- array = cJSON_GetArrayItem(item, 0);
- if( NULL != array )
- {
- cJSON *led_item;
-
- if( NULL != (led_item=cJSON_GetObjectItem(array , "red")) )
- {
- log_info("turn red led '%s'\n", led_item->valuestring);
- mqtt_turn_led(LED_R, led_item->valuestring);
- }
-
- if( NULL != (led_item=cJSON_GetObjectItem(array , "green")) )
- {
- log_info("turn green led '%s'\n", led_item->valuestring);
- mqtt_turn_led(LED_G, led_item->valuestring);
- }
-
- if( NULL != (led_item=cJSON_GetObjectItem(array , "blue")) )
- {
- log_info("turn blue led '%s'\n", led_item->valuestring);
- mqtt_turn_led(LED_B, led_item->valuestring);
- }
- }
- }
- }
- else
- {
- value = cJSON_Print(item);
-
- /* light controled by relay: {"id":"RPi3B#01", "light":"on"} */
- if( hwconf->relay && !strcasecmp(item->string, "light") )
- {
- if( strcasestr(value, "on") )
- {
- log_info("Turn light on\n");
- turn_relay(RELAY1, ON);
- }
- else if( strcasestr(value, "off") )
- {
- log_info("Turn light off\n");
- turn_relay(RELAY1, OFF);
- }
- }
-
- /* buzzer controled : {"id":"RPi3B#01", "buzzer":"on"} */
- if( hwconf->beeper && !strcasecmp(item->string, "buzzer") )
- {
- if( strcasestr(value, "on") )
- {
- turn_beep(3);
- }
- }
-
- free(value); /* must free it, or it will result memory leak */
- }
- }
-
-}
-
-void sub_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
-{
- mqtt_ctx_t *ctx = (mqtt_ctx_t *)userdata;
-
- cJSON *root = NULL;
- cJSON *item;
- char *value;
-
- if ( !message->payloadlen )
- {
- log_error("%s (null)\n", message->topic);
- return ;
- }
-
- log_debug("Subscriber receive message: '%s'\n", message->payload);
-
- root = cJSON_Parse(message->payload);
- if( !root )
- {
- log_error("cJSON_Parse parser failure: %s\n", cJSON_GetErrorPtr());
- return ;
- }
-
- item = cJSON_GetObjectItem(root, "id");
- if( !item )
- {
- log_error("cJSON_Parse get ID failure: %s\n", cJSON_GetErrorPtr());
- goto cleanup;
- }
-
- value = cJSON_PrintUnformatted(item);
- if( strcasecmp(value, ctx->devid) )
- {
- free(value);
- goto cleanup;
- }
-
- free(value);
- log_info("Subscriber receive message: '%s'\n", message->payload);
-
- proc_json_items(root, ctx);
-
-cleanup:
- cJSON_Delete(root); /* must delete it, or it will result memory leak */
- return ;
-}
-
-
-void *mqtt_sub_worker(void *args)
-{
- mqtt_ctx_t *ctx = (mqtt_ctx_t *)args;
- struct mosquitto *mosq;
- bool session = true;
-
- mosq = mosquitto_new(NULL, session, ctx);
- if( !mosq )
- {
- log_error("mosquitto_new failure\n");
- return NULL;
- }
-
- /* set connnect to broker username and password */
- if( strlen(ctx->uid)> 0 && strlen(ctx->pwd)> 0 )
- mosquitto_username_pw_set(mosq, ctx->uid, ctx->pwd);
-
- /* set callback functions */
- mosquitto_connect_callback_set(mosq, sub_connect_callback);
- mosquitto_disconnect_callback_set(mosq, sub_disconnect_callback);
- mosquitto_message_callback_set(mosq, sub_message_callback);
-
- while( !g_signal.stop )
- {
- /* connect to MQTT broker */
- if( mosquitto_connect(mosq, ctx->host, ctx->port, ctx->keepalive) )
- {
- log_error("Subscriber connect to broker[%s:%d] failure: %s\n", ctx->host, ctx->port, strerror(errno));
- msleep(1000);
- continue;
- }
-
- /* -1: use default timeout 1000ms 1: unused */
- mosquitto_loop_forever(mosq, -1, 1);
- }
-
- mosquitto_destroy(mosq);
- return NULL;
-}
-
diff --git a/project/coreMQTT/makefile b/project/coreMQTT/makefile
deleted file mode 100644
index 49a790f..0000000
--- a/project/coreMQTT/makefile
+++ /dev/null
@@ -1,69 +0,0 @@
-#********************************************************************************
-# Copyright: (C) 2023 LingYun IoT System Studio
-# All rights reserved.
-#
-# Filename: Makefile
-# Description: This file is the project top Makefie
-#
-# Version: 1.0.0(11/08/23)
-# Author: Guo Wenxue <guowenxue@gmail.com>
-# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
-#
-#*******************************************************************************
-
-PRJ_PATH=$(shell pwd)
-APP_NAME = mqttd
-
-BUILD_ARCH=$(shell uname -m)
-ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
- CROSS_COMPILE=arm-linux-gnueabihf-
-endif
-
-# C source files in top-level directory
-SRCFILES = $(wildcard *.c)
-
-# common CFLAGS for our source code
-CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized -D_GNU_SOURCE
-
-# C source file in sub-directory
-SRCS=booster modules coreJSON coreMQTT coreSNTP
-SRCS_PATH=$(patsubst %,${PRJ_PATH}/%,$(SRCS))
-CFLAGS+=$(patsubst %,-I%,$(SRCS_PATH))
-LDFLAGS+=$(patsubst %,-L%,$(SRCS_PATH))
-LIBS=$(patsubst %,-l%,$(SRCS))
-LDFLAGS+=${LIBS}
-
-# Open source libraries
-CFLAGS+=-I ${PRJ_PATH}/openlibs/install/include
-LDFLAGS+=-L ${PRJ_PATH}/openlibs/install/lib
-
-# libraries
-libs=openlibs ${SRCS}
-LDFLAGS+=-lmosquitto -lcjson -lssl -lcrypto -lgpiod
-
-LDFLAGS+=-lpthread
-
-all: entry subdir
- ${CROSS_COMPILE}gcc ${CFLAGS} ${SRCFILES} -o ${APP_NAME} ${LDFLAGS}
- @make install
-
-entry:
- @echo "Building ${APP_NAME} on ${BUILD_ARCH}"
-
-subdir:
- @for dir in ${libs} ; do if [ ! -e $${dir} ] ; then ln -s ../$${dir}; fi; done
- @for dir in ${libs} ; do make -C $${dir} ; done
-
-install:
- cp ${APP_NAME} /tftp
-
-clean:
- @for dir in ${SRCS} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done
- @rm -f ${APP_NAME}
-
-distclean:
- @for dir in ${libs} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done
- @for dir in ${libs} ; do if [ -e $${dir} ] ; then unlink $${dir}; fi; done
- @rm -f ${APP_NAME}
- @rm -f cscope.* tags
-
diff --git a/project/openlibs/cjson/build.sh b/project/openlibs/cjson/build.sh
index a9bfb94..7568ae6 100755
--- a/project/openlibs/cjson/build.sh
+++ b/project/openlibs/cjson/build.sh
@@ -6,7 +6,7 @@
PACK_SUFIX=tar.gz
# LingYun source code FTP server
-LY_FTP=http://main.weike-iot.com:2211/src/
+LY_FTP=http://weike-iot.com:2211/src/
# library download URL address
LIB_URL=$LY_FTP
diff --git a/project/openlibs/libevent/build.sh b/project/openlibs/libevent/build.sh
index a5be912..bdb4834 100755
--- a/project/openlibs/libevent/build.sh
+++ b/project/openlibs/libevent/build.sh
@@ -6,7 +6,7 @@
PACK_SUFIX=tar.gz
# LingYun source code FTP server
-LY_FTP=http://main.weike-iot.com:2211/src/
+LY_FTP=http://weike-iot.com:2211/src/
# library download URL address
LIB_URL=$LY_FTP
diff --git a/project/openlibs/libgpiod/build.sh b/project/openlibs/libgpiod/build.sh
index bff5124..0f45587 100755
--- a/project/openlibs/libgpiod/build.sh
+++ b/project/openlibs/libgpiod/build.sh
@@ -8,7 +8,7 @@
PACK_SUFIX=tar.gz
# LingYun source code FTP server
-LY_FTP=http://main.weike-iot.com:2211/src/
+LY_FTP=http://weike-iot.com:2211/src/
# library download URL address
LIB_URL=$LY_FTP
diff --git a/project/openlibs/makefile b/project/openlibs/makefile
index 7f782e8..022cf08 100644
--- a/project/openlibs/makefile
+++ b/project/openlibs/makefile
@@ -1,6 +1,12 @@
PRJ_PATH=$(shell pwd)
-libs=libgpiod cjson openssl mosquitto libevent
+
+openssl_dir := $(shell ls -d openssl/ 2>/dev/null | sed 's|/||g')
+other_dirs := $(shell ls -d */ 2>/dev/null | grep -v '^install/' | grep -v '^openssl/' | sed 's|/||g')
+libs := $(openssl_dir) $(other_dirs)
+
+# clear CFLAGS
+CLFAGS=
all:
for dir in ${libs} ; do cd ${PRJ_PATH}/$${dir} && ./build.sh ; done
diff --git a/project/openlibs/mosquitto/build.sh b/project/openlibs/mosquitto/build.sh
index 3d1014f..7a0819d 100755
--- a/project/openlibs/mosquitto/build.sh
+++ b/project/openlibs/mosquitto/build.sh
@@ -6,7 +6,7 @@
PACK_SUFIX=tar.gz
# LingYun source code FTP server
-LY_FTP=http://main.weike-iot.com:2211/src/
+LY_FTP=http://weike-iot.com:2211/src/
# library download URL address
LIB_URL=$LY_FTP
diff --git a/project/openlibs/openssl/build.sh b/project/openlibs/openssl/build.sh
index 547556d..c301db3 100755
--- a/project/openlibs/openssl/build.sh
+++ b/project/openlibs/openssl/build.sh
@@ -6,7 +6,7 @@
PACK_SUFIX=tar.gz
# LingYun source code FTP server
-LY_FTP=http://main.weike-iot.com:2211/src/
+LY_FTP=http://weike-iot.com:2211/src/
# library download URL address
LIB_URL=$LY_FTP
diff --git a/project/socketd/booster/database.c b/project/socketd/booster/database.c
deleted file mode 100644
index 93f386a..0000000
--- a/project/socketd/booster/database.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/********************************************************************************
- * Copyright: (C) 2020 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: database.c
- * Description: This library used to operate blob packet in sqlite database.
- *
- * Version: 1.0.0(2020年05月13日)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2020年05月13日 12时14分23秒"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include "database.h"
-#include "logger.h"
-
-/* Blob packet table name */
-#define TABLE_NAME "PackTable"
-
-/* Use static global handler here in order to simplify the API,
- * But it will make this library not thread safe
- */
-static sqlite3 *s_clidb = NULL;
-
-
-/* description: open or create sqlite database if not exist
- * input args:
- * $db_file: sqlite database file name
- * return value: <0: failure 0:ok
- * */
-int database_init(const char *db_file)
-{
- char sql[SQL_COMMAND_LEN]={0};
- char *errmsg = NULL;
-
- if( !db_file )
- {
- log_error("%s() Invalid input arguments\n", __func__);
- return -1;
- }
-
- /*+------------------------------------------+
- *| database already exist, just open it |
- *+------------------------------------------+*/
- if( 0==access(db_file, F_OK) )
- {
- if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) )
- {
- log_error("open database file '%s' failure\n", db_file);
- return -2;
- }
- log_info("open database file '%s' ok\n", db_file);
- return 0;
- }
-
- /*+-----------------------------------------+
- *| database not exist, create and init it |
- *+-----------------------------------------+*/
-
- if( SQLITE_OK != sqlite3_open(db_file, &s_clidb) )
- {
- log_error("create database file '%s' failure\n", db_file);
- return -2;
- }
-
- /* SQLite continues without syncing as soon as it has handed data off to the operating system */
- sqlite3_exec(s_clidb, "pragma synchronous = OFF; ", NULL, NULL, NULL);
-
- /* enable full auto vacuum, Auto increase/decrease */
- sqlite3_exec(s_clidb, "pragma auto_vacuum = 2 ; ", NULL, NULL, NULL);
-
- /* Create firehost table in the database */
- snprintf(sql, sizeof(sql), "CREATE TABLE %s(packet BLOB);", TABLE_NAME);
- if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, NULL, &errmsg) )
- {
- log_error("create data_table in database file '%s' failure: %s\n", db_file, errmsg);
- sqlite3_free(errmsg); /* free errmsg */
- sqlite3_close(s_clidb); /* close databse */
- unlink(db_file); /* remove database file */
- return -3;
- }
-
- log_info("create and init database file '%s' ok\n", db_file);
- return 0;
-}
-
-
-/* description: close sqlite database handler
- * return value: none
- */
-void database_term(void)
-{
- log_warn("close sqlite database now\n");
- sqlite3_close(s_clidb);
-
- return ;
-}
-
-
-/* description: push a blob packet into database
- * input args:
- * $pack: blob packet data address
- * $size: blob packet data bytes
- * return value: <0: failure 0:ok
- */
-int database_push_packet(void *pack, int size)
-{
- char sql[SQL_COMMAND_LEN]={0};
- int rv = 0;
- sqlite3_stmt *stat = NULL;
-
- if( !pack || size<=0 )
- {
- log_error("%s() Invalid input arguments\n", __func__);
- return -1;
- }
-
- if( ! s_clidb )
- {
- log_error("sqlite database not opened\n");
- return -2;
- }
-
- snprintf(sql, sizeof(sql), "INSERT INTO %s(packet) VALUES(?)", TABLE_NAME);
- rv = sqlite3_prepare_v2(s_clidb, sql, -1, &stat, NULL);
- if(SQLITE_OK!=rv || !stat)
- {
- log_error("blob add sqlite3_prepare_v2 failure\n");
- rv = -2;
- goto OUT;
- }
-
- if( SQLITE_OK != sqlite3_bind_blob(stat, 1, pack, size, NULL) )
- {
- log_error("blob add sqlite3_bind_blob failure\n");
- rv = -3;
- goto OUT;
- }
-
- rv = sqlite3_step(stat);
- if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
- {
- log_error("blob add sqlite3_step failure\n");
- rv = -4;
- goto OUT;
- }
-
-OUT:
- sqlite3_finalize(stat);
-
- if( rv < 0 )
- log_error("add new blob packet into database failure, rv=%d\n", rv);
- else
- log_info("add new blob packet into database ok\n");
-
- return rv;
-}
-
-
-/* description: pop the first blob packet from database
- * input args:
- * $pack: blob packet output buffer address
- * $size: blob packet output buffer size
- * $byte: blob packet bytes
- * return value: <0: failure 0:ok
- */
-int database_pop_packet(void *pack, int size, int *bytes)
-{
- char sql[SQL_COMMAND_LEN]={0};
- int rv = 0;
- sqlite3_stmt *stat = NULL;
- const void *blob_ptr;
-
- if( !pack || size<=0 )
- {
- log_error("%s() Invalid input arguments\n", __func__);
- return -1;
- }
-
- if( ! s_clidb )
- {
- log_error("sqlite database not opened\n");
- return -2;
- }
-
- /* Only query the first packet record */
- snprintf(sql, sizeof(sql), "SELECT packet FROM %s WHERE rowid = (SELECT rowid FROM %s LIMIT 1);", TABLE_NAME, TABLE_NAME);
- rv = sqlite3_prepare_v2(s_clidb, sql, -1, &stat, NULL);
- if(SQLITE_OK!=rv || !stat)
- {
- log_error("firehost sqlite3_prepare_v2 failure\n");
- rv = -3;
- goto out;
- }
-
- rv = sqlite3_step(stat);
- if( SQLITE_DONE!=rv && SQLITE_ROW!=rv )
- {
- log_error("firehost sqlite3_step failure\n");
- rv = -5;
- goto out;
- }
-
- /* 1rd argument<0> means first segement is packet */
- blob_ptr = sqlite3_column_blob(stat, 0);
- if( !blob_ptr )
- {
- rv = -6;
- goto out;
- }
-
- *bytes = sqlite3_column_bytes(stat, 0);
-
- if( *bytes > size )
- {
- log_error("blob packet bytes[%d] larger than bufsize[%d]\n", *bytes, size);
- *bytes = 0;
- rv = -1;
- }
-
- memcpy(pack, blob_ptr, *bytes);
- rv = 0;
-
-out:
- sqlite3_finalize(stat);
- return rv;
-}
-
-
-/* description: remove the first blob packet from database
- * input args: none
- * return value: <0: failure 0:ok
- */
-int database_del_packet(void)
-{
- char sql[SQL_COMMAND_LEN]={0};
- char *errmsg = NULL;
-
- if( ! s_clidb )
- {
- log_error("sqlite database not opened\n");
- return -2;
- }
-
- /* remove packet from db */
- memset(sql, 0, sizeof(sql));
- snprintf(sql, sizeof(sql), "DELETE FROM %s WHERE rowid = (SELECT rowid FROM %s LIMIT 1);", TABLE_NAME, TABLE_NAME);
- if( SQLITE_OK != sqlite3_exec(s_clidb, sql, NULL, 0, &errmsg) )
- {
- log_error("delete first blob packet from database failure: %s\n", errmsg);
- sqlite3_free(errmsg);
- return -2;
- }
- log_warn("delete first blob packet from database ok\n");
-
- /* Vacuum the database */
- sqlite3_exec(s_clidb, "VACUUM;", NULL, 0, NULL);
-
- return 0;
-}
-
diff --git a/project/socketd/booster/database.h b/project/socketd/booster/database.h
deleted file mode 100644
index f64771d..0000000
--- a/project/socketd/booster/database.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/********************************************************************************
- * Copyright: (C) 2020 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: database.h
- * Description: This library used to operate blob packet in sqlite database.
- *
- * Version: 1.0.0(2020年05月13日)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2020年05月13日 12时14分23秒"
- *
- ********************************************************************************/
-#ifndef _DATABASE_H_
-#define _DATABASE_H_
-
-#include "sqlite3.h"
-
-#define SQL_COMMAND_LEN 256
-
-/* description: open or create sqlite database if not exist
- * input args:
- * $db_file: sqlite database file name
- * return value: <0: failure 0:ok
- * */
-extern int database_init(const char *db_file);
-
-
-/* description: close sqlite database handler
- * return value: none
- */
-extern void database_term(void);
-
-
-/* description: push a blob packet into database
- * input args:
- * $pack: blob packet data address
- * $size: blob packet data bytes
- * return value: <0: failure 0:ok
- */
-extern int database_push_packet(void *pack, int size);
-
-
-/* description: pop the first blob packet from database
- * input args:
- * $pack: blob packet output buffer address
- * $size: blob packet output buffer size
- * $byte: blob packet bytes
- * return value: <0: failure 0:ok
- */
-extern int database_pop_packet(void *pack, int size, int *bytes);
-
-
-/* description: remove the first blob packet from database
- * input args: none
- * return value: <0: failure 0:ok
- */
-extern int database_del_packet(void);
-
-
-#endif /* ----- #ifndef _DATABASE_H_ ----- */
diff --git a/project/socketd/booster/ds18b20.c b/project/socketd/booster/ds18b20.c
deleted file mode 100644
index aa1e01b..0000000
--- a/project/socketd/booster/ds18b20.c
+++ /dev/null
@@ -1,118 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2023 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: ds18b20.c
- * Description: This file is temperature sensor DS18B20 code
- *
- * Version: 1.0.0(2023/8/10)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2023/8/10 12:13:26"
- *
- * Pin connection:
- *
- * DS18B20 Module Raspberry Pi Board
- * VCC <-----> #Pin1(3.3V)
- * DQ <-----> #Pin7(BCM GPIO4)
- * GND <-----> GND
- *
- * /boot/config.txt:
- *
- * dtoverlay=w1-gpio-pullup,gpiopin=4
- *
- ********************************************************************************/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <string.h>
-#include <time.h>
-#include <errno.h>
-
-#include "logger.h"
-
-/* File Content:
- pi@raspberrypi:~/guowenxue $ cat /sys/bus/w1/devices/28-041731f7c0ff/w1_slave
- 3a 01 4b 46 7f ff 0c 10 a5 : crc=a5 YES
- 3a 01 4b 46 7f ff 0c 10 a5 t=19625
- */
-
-int ds18b20_get_temperature(float *temp)
-{
- char w1_path[50] = "/sys/bus/w1/devices/";
- char chip[20];
- char buf[128];
- DIR *dirp;
- struct dirent *direntp;
- int fd =-1;
- char *ptr;
- int found = 0;
-
- if( !temp )
- {
- return -1;
- }
-
- /*+-------------------------------------------------------------------+
- *| open dierectory /sys/bus/w1/devices to get chipset Serial Number |
- *+-------------------------------------------------------------------+*/
- if((dirp = opendir(w1_path)) == NULL)
- {
- log_error("opendir error: %s\n", strerror(errno));
- return -2;
- }
-
- while((direntp = readdir(dirp)) != NULL)
- {
- if(strstr(direntp->d_name,"28-"))
- {
- /* find and get the chipset SN filename */
- strcpy(chip,direntp->d_name);
- found = 1;
- break;
- }
- }
- closedir(dirp);
-
- if( !found )
- {
- log_error("Can not find ds18b20 in %s\n", w1_path);
- return -3;
- }
-
- /* get DS18B20 sample file full path: /sys/bus/w1/devices/28-xxxx/w1_slave */
- strncat(w1_path, chip, sizeof(w1_path)-strlen(w1_path));
- strncat(w1_path, "/w1_slave", sizeof(w1_path)-strlen(w1_path));
-
- /* open file /sys/bus/w1/devices/28-xxxx/w1_slave to get temperature */
- if( (fd=open(w1_path, O_RDONLY)) < 0 )
- {
- log_error("open %s error: %s\n", w1_path, strerror(errno));
- return -4;
- }
-
- if(read(fd, buf, sizeof(buf)) < 0)
- {
- log_error("read %s error: %s\n", w1_path, strerror(errno));
- return -5;
- }
-
- ptr = strstr(buf, "t=");
- if( !ptr )
- {
- log_error("ERROR: Can not get temperature\n");
- return -6;
- }
-
- ptr+=2;
-
- /* convert string value to float value */
- *temp = atof(ptr)/1000;
-
- close(fd);
-
- return 0;
-}
diff --git a/project/socketd/booster/ds18b20.h b/project/socketd/booster/ds18b20.h
deleted file mode 100644
index e756134..0000000
--- a/project/socketd/booster/ds18b20.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2023 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: ds18b20.h
- * Description: This file is temperature sensor DS18B20 code
- *
- * Version: 1.0.0(2023/8/10)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "2023/8/10 12:13:26"
- *
- * Pin connection:
- *
- * DS18B20 Module Raspberry Pi Board
- * VCC <-----> #Pin1(3.3V)
- * DQ <-----> #Pin7(BCM GPIO4)
- * GND <-----> GND
- *
- * /boot/config.txt:
- *
- * dtoverlay=w1-gpio-pullup,gpiopin=4
- *
- ********************************************************************************/
-
-#ifndef _DS18B20_H_
-#define _DS18B20_H_
-
-extern int ds18b20_get_temperature(float *temp);
-
-#endif /* ----- #ifndef _DS18B20_H_ ----- */
-
diff --git a/project/socketd/booster/logger.c b/project/socketd/booster/logger.c
deleted file mode 100644
index ea93dd7..0000000
--- a/project/socketd/booster/logger.c
+++ /dev/null
@@ -1,279 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2023 LingYun IoT System Studio.
- * All rights reserved.
- *
- * Filename: logger.c
- * Description: This file is common logger API functions
- *
- * Version: 1.0.0(11/08/23)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <pthread.h>
-
-#include "logger.h"
-
-typedef void (*log_LockFn)(void *udata, int lock);
-
-static struct {
- char file[32]; /* logger file name */
- FILE *fp; /* logger file pointer */
- long size; /* logger file max size */
- int level; /* logger level */
- log_LockFn lockfn; /* lock function */
- void *udata; /* lock data */
-} L;
-
-static const char *level_names[] = {
- "ERROR",
- "WARN",
- "INFO",
- "DEBUG",
- "TRACE"
-};
-
-static const char *level_colors[] = {
- "\x1b[31m",
- "\x1b[33m",
- "\x1b[32m",
- "\x1b[36m",
- "\x1b[94m"
-};
-
-static inline void time_to_str(char *buf)
-{
- struct timeval tv;
- struct tm *tm;
- int len;
-
- gettimeofday(&tv, NULL);
- tm = localtime(&tv.tv_sec);
-
- len = sprintf(buf, "%04d-%02d-%02d %02d:%02d:%02d.%06d ",
- tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
- tm->tm_hour, tm->tm_min, tm->tm_sec, (int)tv.tv_usec);
-
- buf[len] = '\0';
-}
-
-static void mutex_lock(void *udata, int lock)
-{
- int err;
- pthread_mutex_t *l = (pthread_mutex_t *) udata;
-
- if (lock)
- {
- if ( (err = pthread_mutex_lock(l)) != 0 )
- log_error("Unable to lock log lock: %s", strerror(err));
- }
- else
- {
- if ( (err = pthread_mutex_unlock(l)) != 0 )
- log_error("Unable to unlock log lock: %s", strerror(err));
- }
-}
-
-int log_open(char *fname, int level, int size, int lock)
-{
- FILE *fp;
-
- L.level = level;
- L.size = size*1024;
-
- if( !fname || !strcmp(fname, "console") || !strcmp(fname, "stderr") )
- {
- strcpy(L.file, "console");
- L.fp = stderr;
- L.size = 0; /* console don't need rollback */
- }
- else
- {
- if ( !(fp = fopen(fname, "a+")) )
- {
- fprintf(stderr, "%s() failed: %s\n", __func__, strerror(errno));
- return -2;
- }
- L.fp = fp;
- strncpy(L.file, fname, sizeof(L.file));
- }
-
-
- if( lock )
- {
- static pthread_mutex_t log_lock;
-
- pthread_mutex_init(&log_lock, NULL);
- L.udata = (void *)&log_lock;
- L.lockfn = mutex_lock;
- }
-
- fprintf(L.fp, "\n");
- log_info("logger system(%s) start: file:\"%s\", level:%s, maxsize:%luKiB\n\n",
- LOG_VERSION, L.file, level_names[level], size);
-
- return 0;
-}
-
-void log_close(void)
-{
- if( L.fp && L.fp!=stderr )
- fclose(L.fp);
-
- if (L.udata )
- pthread_mutex_destroy( L.udata);
-}
-
-static void log_rollback(void)
-{
- char cmd[128]={0};
- long fsize;
-
- /* don't need rollback */
- if(L.size <= 0 )
- return ;
-
- fsize = ftell(L.fp);
- if( fsize < L.size )
- return ;
-
- /* backup current log file */
- snprintf(cmd, sizeof(cmd), "cp %s %s.bak", L.file, L.file);
- system(cmd);
-
- /* rollback file */
- fseek(L.fp, 0, SEEK_SET);
- truncate(L.file, 0);
-
- fprintf(L.fp, "\n");
- log_info("logger system(%s) rollback: file:\"%s\", level:%s, maxsize:%luKiB\n\n",
- LOG_VERSION, L.file, level_names[L.level], L.size/1024);
-
- return ;
-}
-
-void _log_write(int level, const char *file, int line, const char *fmt, ...)
-{
- va_list args;
- char time_string[100];
-
- if ( !L.fp || level>L.level )
- return;
-
- /* Acquire lock */
- if ( L.lockfn )
- L.lockfn(L.udata, 1);
-
- log_rollback();
-
- /* check and rollback file */
- time_to_str(time_string);
-
- /* Log to stderr */
- if ( L.fp == stderr )
- {
- fprintf(L.fp, "%s %s %-5s\x1b[0m \x1b[90m%s:%03d:\x1b[0m ",
- time_string, level_colors[level], level_names[level], file, line);
- }
- else /* Log to file */
- {
- fprintf(L.fp, "%s %-5s %s:%03d: ", time_string, level_names[level], file, line);
- }
-
- va_start(args, fmt);
- vfprintf(L.fp, fmt, args);
- va_end(args);
-
- fflush(L.fp);
-
- /* Release lock */
- if ( L.lockfn )
- L.lockfn(L.udata, 0);
-}
-
-#define LINELEN 81
-#define CHARS_PER_LINE 16
-static char *print_char =
-" "
-" "
-" !\"#$%&'()*+,-./"
-"0123456789:;<=>?"
-"@ABCDEFGHIJKLMNO"
-"PQRSTUVWXYZ[\\]^_"
-"`abcdefghijklmno"
-"pqrstuvwxyz{|}~ "
-" "
-" "
-" ???????????????"
-"????????????????"
-"????????????????"
-"????????????????"
-"????????????????"
-"????????????????";
-
-void log_dump(int level, const char *prompt, char *buf, size_t len)
-{
- int rc;
- int idx;
- char prn[LINELEN];
- char lit[CHARS_PER_LINE + 2];
- char hc[4];
- short line_done = 1;
-
- if (!L.fp || level>L.level)
- return;
-
- if( prompt )
- _log_write(level, __FILE__, __LINE__, "%s", prompt);
-
- rc = len;
- idx = 0;
- lit[CHARS_PER_LINE] = '\0';
-
- while (rc > 0)
- {
- if (line_done)
- snprintf(prn, LINELEN, "%08X: ", idx);
-
- do
- {
- unsigned char c = buf[idx];
- snprintf(hc, 4, "%02X ", c);
- strncat(prn, hc, LINELEN);
-
- lit[idx % CHARS_PER_LINE] = print_char[c];
- }
- while (--rc > 0 && (++idx % CHARS_PER_LINE != 0));
-
- line_done = (idx % CHARS_PER_LINE) == 0;
- if (line_done)
- {
- if (L.fp)
- fprintf(L.fp, "%s %s\n", prn, lit);
- }
- }
-
- if (!line_done)
- {
- int ldx = idx % CHARS_PER_LINE;
- lit[ldx++] = print_char[(int)buf[idx]];
- lit[ldx] = '\0';
-
- while ((++idx % CHARS_PER_LINE) != 0)
- strncat(prn, " ", sizeof(prn)-strlen(prn));
-
- if (L.fp)
- fprintf(L.fp, "%s %s\n", prn, lit);
-
- }
-}
diff --git a/project/socketd/booster/logger.h b/project/socketd/booster/logger.h
deleted file mode 100644
index 6f1f7e7..0000000
--- a/project/socketd/booster/logger.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2023 LingYun IoT System Studio.
- * All rights reserved.
- *
- * Filename: logger.h
- * Description: This file is common logger API functions
- *
- * Version: 1.0.0(11/08/23)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
- *
- ********************************************************************************/
-
-#ifndef _LOGGER_H_
-#define _LOGGER_H_
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#define LOG_VERSION "v0.1"
-
-/* log level */
-enum {
- LOG_LEVEL_ERROR,
- LOG_LEVEL_WARN,
- LOG_LEVEL_INFO,
- LOG_LEVEL_DEBUG,
- LOG_LEVEL_TRACE,
- LOG_LEVEL_MAX
-};
-
-enum {
- LOG_LOCK_DISABLE, /* disable lock */
- LOG_LOCK_ENABLE, /* enable lock */
-};
-
-#define ROLLBACK_NONE 0
-
-/* description: Initial the logger system
- * arguments :
- * $fname: logger file name, NULL/"console"/"stderr" will log to console
- * $level: logger level above;
- * $size : logger file max size in KiB
- * $lock : thread lock enable or not
- * return : <0: Failed ==0: Sucessfully
- */
-#define THREAD_LOCK_NONE 0
-#define THREAD_LOCK_EN 1
-int log_open(char *fname, int level, int size, int lock);
-
-
-/* description: Terminate the logger system */
-void log_close(void);
-
-
-/* description: log message into log file. Don't call this function directly. */
-void _log_write(int level, const char *file, int line, const char *fmt, ...);
-
-
-/* description: dump a buffer in hex to logger file */
-void log_dump(int level, const char *prompt, char *buf, size_t len);
-
-/* function: log message into logger file with different log level */
-#define log_trace(...) _log_write(LOG_LEVEL_TRACE, __FILE__, __LINE__, __VA_ARGS__)
-#define log_debug(...) _log_write(LOG_LEVEL_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
-#define log_info(...) _log_write(LOG_LEVEL_INFO, __FILE__, __LINE__, __VA_ARGS__)
-#define log_warn(...) _log_write(LOG_LEVEL_WARN, __FILE__, __LINE__, __VA_ARGS__)
-#define log_error(...) _log_write(LOG_LEVEL_ERROR, __FILE__, __LINE__, __VA_ARGS__)
-
-#endif
diff --git a/project/socketd/booster/makefile b/project/socketd/booster/makefile
deleted file mode 100644
index b6ece0e..0000000
--- a/project/socketd/booster/makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-#********************************************************************************
-# Copyright: (C) 2023 LingYun IoT System Studio
-# All rights reserved.
-#
-# Filename: Makefile
-# Description: This file used compile all the source code to static library
-#
-# Version: 1.0.0(11/08/23)
-# Author: Guo Wenxue <guowenxue@gmail.com>
-# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
-#
-#*******************************************************************************
-
-PWD=$(shell pwd )
-
-BUILD_ARCH=$(shell uname -m)
-ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
- CROSS_COMPILE?=arm-linux-gnueabihf-
-endif
-
-LIBNAME=$(shell basename ${PWD} )
-TOPDIR=$(shell dirname ${PWD} )
-CFLAGS+=-D_GNU_SOURCE
-
-all: clean
- @rm -f *.o
- @${CROSS_COMPILE}gcc ${CFLAGS} -I${TOPDIR} -c *.c
- ${CROSS_COMPILE}ar -rcs lib${LIBNAME}.a *.o
-
-clean:
- @rm -f *.o
- @rm -f *.a
-
-distclean:
- @make clean
diff --git a/project/socketd/booster/packet.c b/project/socketd/booster/packet.c
deleted file mode 100644
index ec51dd4..0000000
--- a/project/socketd/booster/packet.c
+++ /dev/null
@@ -1,207 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2022 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: packet.c
- * Description: This file is packet API functions
- *
- * Version: 1.0.0(18/04/22)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "18/04/22 16:30:25"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <time.h>
-#include "packet.h"
-#include "logger.h"
-#include "ds18b20.h"
-
-int get_devid(char *devid, int size, int sn)
-{
- if( !devid || size<DEVID_LEN )
- {
- log_error("Invalid input arugments\n");
- return -1;
- }
-
- memset(devid, 0, size);
- snprintf(devid, size, "RPI3B2505%04d", sn);
- return 0;
-}
-
-int get_time(struct tm *ptm)
-{
- if( !ptm )
- {
- log_error("Invalid input arugments\n");
- return -1;
- }
-
- time_t now = time(NULL);
- localtime_r(&now, ptm);
-
- return 0;
-}
-
-int packet_segmented_pack(pack_info_t *pack_info, uint8_t *pack_buf, int size)
-{
- char strtime[TIME_LEN] = {'\0'};
- struct tm *ptm;
- char *buf = (char *)pack_buf;
-
- if( !pack_info || !buf || size<=0 )
- {
- log_error("Invalid input arguments\n");
- return -1;
- }
-
- ptm = &pack_info->sample_time;
- snprintf(strtime, sizeof(strtime), "%04d-%02d-%02d %02d:%02d:%02d",
- ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
- ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
-
- memset(buf, 0, size);
- snprintf(buf, size, "%s|%s|%.3f", pack_info->devid, strtime, pack_info->temper);
-
- return strlen(buf);
-}
-
-int packet_json_pack(pack_info_t *pack_info, uint8_t *pack_buf, int size)
-{
- char strtime[TIME_LEN] = {'\0'};
- struct tm *ptm;
- char *buf = (char *)pack_buf;
-
- if( !pack_info || !buf || size<=0 )
- {
- log_error("Invalid input arguments\n");
- return -1;
- }
-
- ptm = &pack_info->sample_time;
- snprintf(strtime, sizeof(strtime), "%04d-%02d-%2d %02d:%02d:%02d",
- ptm->tm_year+1900, ptm->tm_mon+1, ptm->tm_mday,
- ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
-
- memset(buf, 0, size);
- snprintf(buf, size, "{\"devid\":\"%s\", \"time\":\"%s\",\"temperature\":\"%.3f\"}",
- pack_info->devid, strtime, pack_info->temper);
-
- return strlen(buf);
-}
-
-/*
- * The CRC-ITU-T, also known as CRC-16-ITU-T or CRC-16-V.41, uses the polynomial:
- * 0x1021: x^16 + x^12 + x^5 + 1
- */
-
-#define CRC16_ITU_T_POLY 0x1021 /* Define the CRC-ITU-T polynomial */
-static uint16_t crc_itu_t(const uint8_t *data, size_t length)
-{
- uint16_t crc = 0xFFFF;
- size_t i, j;
-
- for (i=0; i<length; i++)
- {
- crc ^= ((uint16_t)data[i] << 8);
-
- for(j=0; j<8; j++)
- {
- if (crc & 0x8000)
- {
- crc = (crc << 1) ^ CRC16_ITU_T_POLY;
- }
- else
- {
- crc <<= 1;
- }
- }
- }
-
- return crc;
-}
-
-uint16_t to_big_endian(uint16_t num)
-{
- return (num << 8) | (num >> 8);
-}
-
-/* TLV(Tag Length Value) PDU(Protocal Data Unit) format:
- *
- * +-----------+-----------+------------+-------------+-------------+
- * | Header(2B)| Tag(1B) | Length(2B) | Value(nB) | CRC16(2B) |
- * +-----------+-----------+------------+-------------+-------------+
- *
- * Header(2B): 0xFE 0xFD
- * Tag(1B): 0x01->temperature 0x02->Humidity 0x03->Noisy ...
- * Length(2B): Data value length
- * Value(nB): Data value
- * CRC16(2B): CRC from Header to Value
- */
-
-int packet_tlv_pack(pack_info_t *pack_info, uint8_t *pack_buf, int size)
-{
- struct tm *ptm;
- int ofset = 0;
- uint16_t crc;
-
- if( !pack_info || !pack_buf || size<TLV_MINSIZE )
-
- {
- log_error("Invalid input arguments\n");
- return -1;
- }
-
- /*+----------------------+
- *| TLV Header(2B) |
- *+----------------------+*/
- *(uint16_t *)pack_buf = to_big_endian(TLV_HEADER);
- ofset += 2;
-
- /*+----------------------+
- *| TLV Tag(1B) |
- *+----------------------+*/
- pack_buf[ofset++] = TAG_TEMPERATURE;
-
- /* Skip data length here, we will calculate it later */
- ofset += 2;
-
- /*+----------------------+
- *| payload data value |
- *+----------------------+*/
-
- /* 6 bytes sample time */
- ptm = &pack_info->sample_time;
- pack_buf[ofset++] = (uint8_t)(ptm->tm_year+1900-2000);
- pack_buf[ofset++] = (uint8_t)(ptm->tm_mon+1);
- pack_buf[ofset++] = (uint8_t)(ptm->tm_mday);
- pack_buf[ofset++] = (uint8_t)(ptm->tm_hour);
- pack_buf[ofset++] = (uint8_t)(ptm->tm_min);
- pack_buf[ofset++] = (uint8_t)(ptm->tm_sec);
-
- /* 8 bytes device SN */
- strncpy((char *)(pack_buf+ofset), pack_info->devid, DEVID_LEN);
- ofset += DEVID_LEN;
-
- /* 2 bytes temperature value */
- pack_buf[ofset++] = (int)pack_info->temper; /* integer part */
- pack_buf[ofset++] = (((int)(pack_info->temper*100))%100); /* fractional part */
-
- /*+----------------------+
- *| TLV Length(2B) |
- *+----------------------+*/
- *(uint16_t *)(pack_buf+3) = (ofset-5);
-
- /*+----------------------+
- *| TLV CRC(2B) |
- *+----------------------+*/
- crc = crc_itu_t(pack_buf, ofset);
- *(uint16_t *)(pack_buf+ofset) = crc;
- ofset += 2;
-
- return ofset;
-}
-
diff --git a/project/socketd/booster/packet.h b/project/socketd/booster/packet.h
deleted file mode 100644
index 70e556a..0000000
--- a/project/socketd/booster/packet.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/********************************************************************************
- * Copyright: (C) 2022 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: packet.h
- * Description: This head file is packet API functions.
- *
- * Version: 1.0.0(18/04/22)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "18/04/22 16:24:40"
- *
- ********************************************************************************/
-
-
-#ifndef _PACKET_H_
-#define _PACKET_H_
-
-#include <stdint.h>
-#include <time.h>
-
-#define DEVID_LEN 8
-#define TIME_LEN 32
-
-typedef struct pack_info_s
-{
- char devid[DEVID_LEN+1]; /* device ID */
- struct tm sample_time; /* sample time */
- float temper; /* sample temperature */
-} pack_info_t;
-
-/* packet function pointer type */
-typedef int (* pack_proc_t)(pack_info_t *pack_info, uint8_t *pack_buf, int size);
-
-/* description: get device ID
- * input args:
- * $devid : device ID string
- * $size : device ID output buffer size
- * $sn : serial number
- * return value: <0: failure 0:ok
- */
-extern int get_devid(char *devid, int size, int sn);
-
-/* description: get current system in struct tm
- * input args:
- * $sample_time: sample time in struct tm
- * return value: <0: failure 0:ok
- */
-extern int get_time(struct tm *sample_time);
-
-/* description: package a string packet in format "devid|time|temper"
- * input args:
- * $pack_info: packet data contains devid, time and temperature
- * $pack_buf : packet output buffer
- * $size : packet output buffer size
- * return value: <0: failure >0: packet bytes
- */
-extern int packet_segmented_pack(pack_info_t *pack_info, uint8_t *pack_buf, int size);
-
-
-/* description: package a json string packet: {"devid":"xxx", "time":"xxx", "temperature":"xxx"}
- * input args:
- * $pack_info: packet data contains devid, time and temperature
- * $pack_buf : packet output buffer
- * $size : packet output buffer size
- * return value: <0: failure >0: packet bytes
- */
-extern int packet_json_pack(pack_info_t *pack_info, uint8_t *pack_buf, int size);
-
-
-/* TLV(Tag Length Value) PDU(Protocal Data Unit) format:
- *
- * +-----------+-----------+------------+-------------+-------------+
- * | Header(2B)| Tag(1B) | Length(2B) | Value(nB) | CRC16(2B) |
- * +-----------+-----------+------------+-------------+-------------+
- *
- * Header(2B): 0xFE 0xED
- * Tag(1B): 0x01->temperature 0x02->Humidity 0x03->Noisy ...
- * Length(2B): Data length
- * Value(nB): Data value
- * CRC16(2B): CRC from Header to Value
- */
-
-/* TLV Header */
-#define TLV_HEADER 0xFEED
-
-/* TLV bytes without payload: Header(2B)+Tag(1B)+Length(2B)+CRC16(2B) */
-#define TLV_MINSIZE 7
-
-/* TVL Tag definition */
-enum
-{
- TAG_TEMPERATURE = 1,
- TAG_HUMIDITY,
- TAG_NOISY,
-};
-
-/* description: package a TLV packet: 0xFD 0xFE
- * input args:
- * $pack_info: packet data contains devid, time and temperature
- * $pack_buf : packet output buffer
- * $size : packet output buffer size
- * return value: <0: failure >0: packet bytes
- */
-
-int packet_tlv_pack(pack_info_t *pack_info, uint8_t *pack_buf, int size);
-
-#endif /* ----- #ifndef _PACKET_H_ ----- */
diff --git a/project/socketd/booster/proc.c b/project/socketd/booster/proc.c
deleted file mode 100644
index b55b202..0000000
--- a/project/socketd/booster/proc.c
+++ /dev/null
@@ -1,432 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2020 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: proc.c
- * Description: This file is the process API
- *
- * Version: 1.0.0(7/06/2020)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "7/06/2020 09:19:02 PM"
- *
- ********************************************************************************/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "proc.h"
-#include "logger.h"
-
-proc_signal_t g_signal={0};
-
-void proc_default_sighandler(int sig)
-{
- switch(sig)
- {
- case SIGINT:
- log_warn("SIGINT - stopping\n");
- g_signal.stop = 1;
- break;
-
- case SIGTERM:
- log_warn("SIGTERM - stopping\n");
- g_signal.stop = 1;
- break;
-
- case SIGSEGV:
- log_warn("SIGSEGV - stopping\n");
-#if 0
- if(g_signal.stop)
- exit(0);
-
- g_signal.stop = 1;
-#endif
- break;
-
- case SIGPIPE:
- log_warn("SIGPIPE - warnning\n");
- break;
-
- default:
- break;
- }
-}
-
-
-/* install default signal process functions */
-void install_default_signal(void)
-{
- struct sigaction sigact, sigign;
-
- log_info("Install default signal handler.\n");
-
- /* Initialize the catch signal structure. */
- sigemptyset(&sigact.sa_mask);
- sigact.sa_flags = 0;
- sigact.sa_handler = proc_default_sighandler;
-
- /* Setup the ignore signal. */
- sigemptyset(&sigign.sa_mask);
- sigign.sa_flags = 0;
- sigign.sa_handler = SIG_IGN;
-
- sigaction(SIGTERM, &sigact, 0); /* catch terminate signal "kill" command */
- sigaction(SIGINT, &sigact, 0); /* catch interrupt signal CTRL+C */
- //sigaction(SIGSEGV, &sigact, 0); /* catch segmentation faults */
- sigaction(SIGPIPE, &sigact, 0); /* catch broken pipe */
-#if 0
- sigaction(SIGCHLD, &sigact, 0); /* catch child process return */
- sigaction(SIGUSR2, &sigact, 0); /* catch USER signal */
-#endif
-}
-
-
-/* ****************************************************************************
- * FunctionName: daemonize
- * Description : Set the programe runs as daemon in background
- * Inputs : nodir: DON'T change the work directory to / : 1:NoChange 0:Change
- * noclose: close the opened file descrtipion or not 1:Noclose 0:Close
- * Output : NONE
- * Return : NONE
- * *****************************************************************************/
-void daemonize(int nochdir, int noclose)
-{
- int rv, fd;
- int i;
-
- /* already a daemon */
- if (1 == getppid())
- return;
-
- /* fork error */
- rv = fork();
- if (rv < 0) exit(1);
-
- /* parent process exit */
- if (rv > 0)
- exit(0);
-
- /* obtain a new process session group */
- setsid();
-
- if (!noclose)
- {
- /* close all descriptors */
- for (i = getdtablesize(); i >= 0; --i)
- {
- //if (i != g_logPtr->fd)
- close(i);
- }
-
- /* Redirect Standard input [0] to /dev/null */
- fd = open("/dev/null", O_RDWR);
-
- /* Redirect Standard output [1] to /dev/null */
- dup(fd);
-
- /* Redirect Standard error [2] to /dev/null */
- dup(fd);
- }
-
- umask(0);
-
- if (!nochdir)
- chdir("/");
-
- return;
-}
-
-/* ****************************************************************************
- * FunctionName: check_set_program_running
- * Description : check program already running or not, if not then run it and
- * record pid into $pidfile
- * Inputs : daemon: set program running in daemon or not
- * pid_file:The record PID file path
- * Output : NONE
- * Return : 0: Record successfully Else: Failure
- * *****************************************************************************/
-
-int check_set_program_running(int daemon, char *pidfile)
-{
- if( !pidfile )
- return 0;
-
- if( check_daemon_running(pidfile) )
- {
- log_error("Program already running, process exit now\n");
- return -1;
- }
-
- if( daemon )
- {
- if( set_daemon_running(pidfile) < 0 )
- {
- log_error("set program running as daemon failure\n");
- return -2;
- }
- }
- else
- {
- if( record_daemon_pid(pidfile) < 0 )
- {
- log_error("record program running PID failure\n");
- return -3;
- }
- }
-
- return 0;
-}
-
-
-
-/* ****************************************************************************
- * FunctionName: record_daemon_pid
- * Description : Record the running daemon program PID to the file "pid_file"
- * Inputs : pid_file:The record PID file path
- * Output : NONE
- * Return : 0: Record successfully Else: Failure
- * *****************************************************************************/
-int record_daemon_pid(const char *pid_file)
-{
- struct stat fStatBuf;
- int fd = -1;
- int mode = S_IROTH | S_IXOTH | S_IRGRP | S_IXGRP | S_IRWXU;
- char ipc_dir[64] = { 0 };
-
- strncpy(ipc_dir, pid_file, 64);
-
- /* dirname() will modify ipc_dir and save the result */
- dirname(ipc_dir);
-
- /* If folder pid_file PATH doesnot exist, then we will create it" */
- if (stat(ipc_dir, &fStatBuf) < 0)
- {
- if (mkdir(ipc_dir, mode) < 0)
- {
- log_error("cannot create %s: %s\n", ipc_dir, strerror(errno));
- return -1;
- }
-
- (void)chmod(ipc_dir, mode);
- }
-
- /* Create the process running PID file */
- mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
- if ((fd = open(pid_file, O_RDWR | O_CREAT | O_TRUNC, mode)) >= 0)
- {
- char pid[PID_ASCII_SIZE];
- snprintf(pid, sizeof(pid), "%u\n", (unsigned)getpid());
- write(fd, pid, strlen(pid));
- close(fd);
-
- log_debug("Record PID<%u> to file %s.\n", getpid(), pid_file);
- }
- else
- {
- log_error("cannot create %s: %s\n", pid_file, strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
-/* ****************************************************************************
- * FunctionName: get_daemon_pid
- * Description : Get the daemon process PID from the PID record file "pid_file"
- * Inputs : pid_file: the PID record file
- * Output : NONE
- * Return : pid_t: The daemon process PID number
- * *****************************************************************************/
-pid_t get_daemon_pid(const char *pid_file)
-{
- FILE *f;
- pid_t pid;
-
- if ((f = fopen(pid_file, "rb")) != NULL)
- {
- char pid_ascii[PID_ASCII_SIZE];
- (void)fgets(pid_ascii, PID_ASCII_SIZE, f);
- (void)fclose(f);
- pid = atoi(pid_ascii);
- }
- else
- {
- log_error("Can't open PID record file %s: %s\n", pid_file, strerror(errno));
- return -1;
- }
- return pid;
-}
-
-/* ****************************************************************************
- * FunctionName: check_daemon_running
- * Description : Check the daemon program already running or not
- * Inputs : pid_file: The record running daemon program PID
- * Output : NONE
- * Return : 1: The daemon program alread running 0: Not running
- * *****************************************************************************/
-int check_daemon_running(const char *pid_file)
-{
- int rv = -1;
- struct stat fStatBuf;
-
- rv = stat(pid_file, &fStatBuf);
- if (0 == rv)
- {
- pid_t pid = -1;
- printf("PID record file \"%s\" exist.\n", pid_file);
-
- pid = get_daemon_pid(pid_file);
- if (pid > 0) /* Process pid exist */
- {
- if ((rv = kill(pid, 0)) == 0)
- {
- printf("Program with PID[%d] seems running.\n", pid);
- return 1;
- }
- else /* Send signal to the old process get no reply. */
- {
- printf("Program with PID[%d] seems exit.\n", pid);
- remove(pid_file);
- return 0;
- }
- }
- else if (0 == pid)
- {
- printf("Can not read program PID form record file.\n");
- remove(pid_file);
- return 0;
- }
- else /* Read pid from file "pid_file" failure */
- {
- printf("Read record file \"%s\" failure, maybe program still running.\n", pid_file);
- return 1;
- }
- }
-
- return 0;
-}
-
-/* ****************************************************************************
- * FunctionName: stop_daemon_running
- * Description : Stop the daemon program running
- * Inputs : pid_file: The record running daemon program PID
- * Output : NONE
- * Return : 1: The daemon program alread running 0: Not running
- * *****************************************************************************/
-int stop_daemon_running(const char *pid_file)
-{
- pid_t pid = -1;
- struct stat fStatBuf;
-
- if ( stat(pid_file, &fStatBuf) < 0)
- return 0;
-
- printf("PID record file \"%s\" exist.\n", pid_file);
- pid = get_daemon_pid(pid_file);
- if (pid > 0) /* Process pid exist */
- {
- while ( (kill(pid, 0) ) == 0)
- {
- kill(pid, SIGTERM);
- sleep(1);
- }
-
- remove(pid_file);
- }
-
- return 0;
-}
-
-
-
-/* ****************************************************************************
- * FunctionName: set_daemon_running
- * Description : Set the programe running as daemon if it's not running and record
- * its PID to the pid_file.
- * Inputs : pid_file: The record running daemon program PID
- * Output : NONE
- * Return : 0: Successfully. 1: Failure
- * *****************************************************************************/
-int set_daemon_running(const char *pid_file)
-{
- daemon(0, 1);
- log_info("Program running as daemon [PID:%d].\n", getpid());
-
- if (record_daemon_pid(pid_file) < 0)
- {
- log_error("Record PID to file \"%s\" failure.\n", pid_file);
- return -2;
- }
-
- return 0;
-}
-
-/* start a new thread to run $thread_workbody point function */
-int thread_start(pthread_t *thread_id, thread_body_t thread_workbody, void *thread_arg)
-{
- int rv = 0;
- pthread_t tid;
-
- pthread_attr_t thread_attr;
-
- /* Initialize the thread attribute */
- rv = pthread_attr_init(&thread_attr);
- if(rv)
- return -1;
-
- /* Set the stack size of the thread */
- rv = pthread_attr_setstacksize(&thread_attr, 120 * 1024);
- if(rv)
- goto CleanUp;
-
- /* Set thread to detached state:Don`t need pthread_join */
- rv = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
- if(rv)
- goto CleanUp;
-
- /* Create the thread */
- rv = pthread_create(&tid, &thread_attr, thread_workbody, thread_arg);
- if(rv)
- goto CleanUp;
-
-CleanUp:
-
-
- if( thread_id )
- {
- if( rv )
- *thread_id = 0;
- else
- *thread_id = tid;
- }
-
- /* Destroy the attributes of thread */
- pthread_attr_destroy(&thread_attr);
- return rv;
-}
-
-
-/* excute a linux command by system() */
-void exec_system_cmd(const char *format, ...)
-{
- char cmd[256];
- va_list args;
-
- memset(cmd, 0, sizeof(cmd));
-
- va_start(args, format);
- vsnprintf(cmd, sizeof(cmd), format, args);
- va_end(args);
-
- system(cmd);
-}
-
-
diff --git a/project/socketd/booster/proc.h b/project/socketd/booster/proc.h
deleted file mode 100644
index 1a8a14e..0000000
--- a/project/socketd/booster/proc.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/********************************************************************************
- * Copyright: (C) 2020 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: proc.h
- * Description: This head file is for Linux process/thread API
- *
- * Version: 1.0.0(7/06/2012~)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "7/06/2012 09:21:33 PM"
- *
- ********************************************************************************/
-
-#ifndef __PROC_H_
-#define __PROC_H_
-
-#include <signal.h>
-#include <time.h>
-
-#define PID_ASCII_SIZE 11
-
-typedef struct proc_signal_s
-{
- int signal;
- unsigned stop; /* 0: Not term 1: Stop */
-} proc_signal_t;
-
-typedef void *(* thread_body_t) (void *thread_arg);
-
-extern proc_signal_t g_signal;
-
-/* install default signal process functions */
-extern void install_default_signal(void);
-
-/* excute a linux command by system() */
-extern void exec_system_cmd(const char *format, ...);
-
-/* check program already running or not, if not then run it and record pid into $pidfile */
-extern int check_set_program_running(int daemon, char *pidfile);
-
-/* check program already running or not from $pid_file */
-extern int check_daemon_running(const char *pid_file);
-
-/* set program daemon running and record pid in $pid_file */
-extern int set_daemon_running(const char *pid_file);
-
-/* record proces ID into $pid_file */
-extern int record_daemon_pid(const char *pid_file);
-
-/* stop program running from $pid_file */
-extern int stop_daemon_running(const char *pid_file);
-
-/* my implementation for set program running in daemon */
-extern void daemonize(int nochdir, int noclose);
-
-/* start a new thread to run $thread_workbody point function */
-extern int thread_start(pthread_t *thread_id, thread_body_t thread_workbody, void *thread_arg);
-
-/* +---------------------+
- * | Low level API |
- * +---------------------+*/
-
-/* get daemon process ID from $pid_file */
-extern pid_t get_daemon_pid(const char *pid_file);
-
-/* +------------------------+
- * | inline functions API |
- * +------------------------+*/
-static inline void msleep(unsigned long ms)
-{
- struct timespec cSleep;
- unsigned long ulTmp;
-
- cSleep.tv_sec = ms / 1000;
- if (cSleep.tv_sec == 0)
- {
- ulTmp = ms * 10000;
- cSleep.tv_nsec = ulTmp * 100;
- }
- else
- {
- cSleep.tv_nsec = 0;
- }
-
- nanosleep(&cSleep, 0);
- return ;
-}
-
-#endif
diff --git a/project/socketd/booster/socket.c b/project/socketd/booster/socket.c
deleted file mode 100644
index 4049bfc..0000000
--- a/project/socketd/booster/socket.c
+++ /dev/null
@@ -1,547 +0,0 @@
-/********************************************************************************
- * Copyright: (C) 2022 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: socket.c
- * Description: This file is for socket API functions
- *
- * Version: 1.0.0(18/04/22)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "18/04/22 17:09:59"
- *
- ********************************************************************************/
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <netdb.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/un.h>
-#include <poll.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <linux/sockios.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <sys/resource.h>
-
-#include "socket.h"
-#include "logger.h"
-
-/* description: initial socket context
- * input args:
- * $sock: socket context pointer
- * $host: connect server hostname for client mode, unused for server mode
- * $port: connect server port for client mode or listen port for server mode
- * return value: <0: failure 0:ok
- */
-int socket_init(socket_ctx_t *sock, char *host, int port)
-{
- if( !sock || port<=0 )
- return -1;
-
- memset( sock, 0, sizeof(*sock) );
- sock->fd = -1;
- sock->port = port;
- if( host ) /* server no need it */
- {
- strncpy(sock->host, host, HOSTNAME_LEN);
- }
-
- return 0;
-}
-
-/* description: close socket
- * input args:
- * $sock: socket context pointer
- * return value: <0: failure 0:ok
- */
-int socket_term(socket_ctx_t *sock)
-{
- if( !sock )
- return -1;
-
- if( sock->fd > 0)
- {
- close(sock->fd);
- sock->fd = -1;
- sock->connected = 0;
- }
-
- return 0;
-}
-
-/* description: socket server start listen
- * input args:
- * $sock: socket context pointer
- * return value: <0: failure 0:ok
- */
-#if 0 /* --TBD-- */
-int socket_listen(socket_ctx_t *sock)
-{
- int rv = 0;
- struct sockaddr_in addr;
- int backlog = 13;
-
- if( !sock )
- return -1;
-
- set_socket_rlimit(); /* set max open socket count */
-}
-#endif
-
-/* description: check socket connect status
- * input args:
- * $sock: socket context pointer
- * return value: 1: connected 0:disconnected
- */
-int socket_connected(socket_ctx_t *sock)
-{
- struct tcp_info info;
- int len=sizeof(info);
- int changed = 0;
-
- if( !sock )
- {
- return 0;
- }
-
- if( sock->fd < 0 )
- {
- /* socket is connected before but got disconnected now */
- changed = sock->connected ? 1 : 0;
- sock->connected = 0;
- goto out;
- }
-
- getsockopt(sock->fd, IPPROTO_TCP, TCP_INFO, &info, (socklen_t *)&len);
- if( TCP_ESTABLISHED==info.tcpi_state )
- {
- /* socket is disconnected before but got connected now */
- changed = !sock->connected ? 1 : 0;
- sock->connected = 1;
- }
- else
- {
- /* socket is connected before but got disconnected now */
- changed = sock->connected ? 1 : 0;
- sock->connected = 0;
- }
-
-out:
- if( changed )
- {
- log_info("socket status got %s\n", sock->connected?"connected":"disconnected");
- }
- return sock->connected;
-}
-
-/* description: socket connect to server in block mode
- * input args:
- * $sock: socket context pointer
- * return value: <0: failure 0:ok
- */
-int socket_connect(socket_ctx_t *sock)
-{
- int rv = 0;
- int sockfd = 0;
- char service[20];
- struct addrinfo hints, *rp;
- struct addrinfo *res = NULL;
- struct in_addr inaddr;
- struct sockaddr_in addr;
- int len = sizeof(addr);
-
- if( !sock )
- return -1;
-
- socket_term(sock);
-
- /*+--------------------------------------------------+
- *| use getaddrinfo() to do domain name translation |
- *+--------------------------------------------------+*/
-
- memset(&hints, 0, sizeof(struct addrinfo));
- hints.ai_family = AF_INET; /* Only support IPv4 */
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = IPPROTO_TCP; /* TCP protocol */
-
- /* If $host is a valid IP address, then don't use name resolution */
- if( inet_aton(sock->host, &inaddr) )
- {
- //log_info("%s is a valid IP address, don't use domain name resolution.\n", sock->host);
- hints.ai_flags |= AI_NUMERICHOST;
- }
-
- /* Obtain address(es) matching host/port */
- snprintf(service, sizeof(service), "%d", sock->port);
- if( (rv=getaddrinfo(sock->host, service, &hints, &res)) )
- {
- log_error("getaddrinfo() parser [%s:%s] failed: %s\n", sock->host, service, gai_strerror(rv));
- return -3;
- }
-
- /* getaddrinfo() returns a list of address structures. Try each
- address until we successfully connect or bind */
- for (rp=res; rp!=NULL; rp=rp->ai_next)
- {
-#if 0
- char ipaddr[INET_ADDRSTRLEN];
- struct sockaddr_in *sp = (struct sockaddr_in *) rp->ai_addr;
-
- /* print domain name translation result */
- memset( ipaddr, 0, sizeof(ipaddr) );
- if( inet_ntop(AF_INET, &sp->sin_addr, ipaddr, sizeof(ipaddr)) )
- {
- log_info("domain name resolution [%s->%s]\n", sock->host, ipaddr);
- }
-#endif
-
- /* Create the socket */
- sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
- if( sockfd < 0)
- {
- log_error("socket() create failed: %s\n", strerror(errno));
- rv = -3;
- continue;
- }
-
- /* connect to server */
- rv = connect(sockfd, rp->ai_addr, len);
- if( 0 == rv )
- {
- sock->fd = sockfd;
- log_info("Connect to server[%s:%d] on fd[%d] successfully!\n", sock->host, sock->port, sockfd);
- break;
- }
- else
- {
- /* socket connect get error, try another IP address */
- close(sockfd);
- continue;
- }
- }
-
- freeaddrinfo(res);
- return rv;
-}
-
-/* description: send data from the socket
- * input args:
- * $sock : socket context pointer
- * $data : socket send data
- * $bytes: socket send data bytes
- * return value: <0: failure 0:ok
- */
-int socket_send(socket_ctx_t *sock, char *data, int bytes)
-{
- int rv = 0;
- int i = 0;
- int left_bytes = bytes;
-
- if( !sock || !data || bytes<= 0 )
- return -1;
-
- while( left_bytes > 0 )
- {
- rv=write(sock->fd, &data[i], left_bytes);
- if( rv < 0 )
- {
- log_info("socket[%d] write() failure: %s, close socket now\n", sock->fd, strerror(errno));
- socket_term(sock);
- return -2;
- }
- else if( rv == left_bytes )
- {
- log_info("socket send %d bytes data over\n", bytes);
- return 0;
- }
- else
- {
- /* not send over this time, continue to send left data */
- i += rv;
- left_bytes -= rv;
- continue;
- }
- }
-
- return 0;
-}
-
-/* description: receive data from the socket
- * input args:
- * $sock : socket context pointer
- * $buf : socket receive data buffer
- * $size : socket receive data buffer size
- * $timeout: receive data time, <=0 will don't timeout
- * return value: <0: failure 0:ok
- */
-int socket_recv(socket_ctx_t *sock, char *buf, int size, int timeout)
-{
- int rv = 0;
- fd_set rdset;
- int maxfd;
-
- if( !sock || !buf || size<= 0 )
- return -1;
-
- memset(buf, 0, size);
-
- maxfd = sock->fd;
- FD_ZERO(&rdset);
- FD_SET(sock->fd, &rdset);
-
- if( timeout <= 0 ) /* no timeout */
- {
- rv=select(maxfd+1, &rdset, NULL, NULL, NULL);
- }
- else
- {
- struct timeval tv;
- tv.tv_sec = timeout;
- tv.tv_usec = 0;
- rv=select(maxfd+1, &rdset, NULL, NULL, &tv);
- }
-
- if( rv < 0 )
- {
- log_error("select() on socket[%d] got error: %s\n", sock->fd, strerror(errno));
- return -2;
- }
- else if( rv == 0 )
- {
- log_error("select() on socket[%d] get timeout\n", sock->fd);
- return 0;
- }
- else
- {
- rv = read(sock->fd, buf, size);
- if( rv <= 0 )
- {
- log_error("socket[%d] read() failure or got disconnected: %s, close socket now\n", sock->fd, strerror(errno));
- socket_term(sock);
- return -2;
- }
- else
- {
- log_debug("socket[%d] receive %d bytes data\n", sock->fd, rv);
- return rv;
- }
- }
-}
-
-
-/*+-------------------------------------------------------------------+
- *| socket utils function |
- *+-------------------------------------------------------------------+*/
-
-/* description: set socket listen port as reusable, fix port already used bug */
-int socket_set_reuseaddr(int sockfd)
-{
- int opt = 1;
- int len = sizeof (int);
-
- if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &opt, len))
- {
- log_error("Set socket[%d] option SO_REUSEADDR failed:%s\n", sockfd, strerror(errno));
- return -1;
- }
- log_debug("Set socket[%d] option SO_REUSEADDR ok\n", sockfd);
-
- return 0;
-}
-
-/* set socket as non-block mode, common socket default work as block mode */
-int socket_set_nonblock(int sockfd)
-{
- int opts;
- /*
- * fcntl may set:
- *
- * EACCES, EAGAIN: Operation is prohibited by locks held by other
- * processes. Or, operation is prohibited because the file has
- * been memory-mapped by another process.
- * EBADF: fd is not an open file descriptor, or the command was F_SETLK
- * or F_SETLKW and the file descriptor open mode doesn't match
- * with the type of lock requested.
- * EDEADLK: It was detected that the specified F_SETLKW command would
- * cause a deadlock.
- * EFAULT: lock is outside your accessible address space.
- * EINTR: For F_SETLKW, the command was interrupted by a signal. For
- * F_GETLK and F_SETLK, the command was interrupted by a signal
- * before the lock was checked or acquired. Most likely when
- * locking a remote file (e.g. locking over NFS), but can
- * sometimes happen locally.
- * EINVAL: For F_DUPFD, arg is negative or is greater than the maximum
- * allowable value. For F_SETSIG, arg is not an allowable signal
- * number.
- * EMFILE: For F_DUPFD, the process already has the maximum number of
- * file descriptors open.
- * ENOLCK: Too many segment locks open, lock table is full, or a remote
- * locking protocol failed (e.g. locking over NFS).
- * EPERM: Attempted to clear the O_APPEND flag on a file that has the
- * append-only attribute set.
- */
- opts = fcntl(sockfd, F_GETFL);
- if (opts < 0)
- {
- log_warn("fcntl() get socket options failure: %s\n", strerror(errno));
- return -1;
- }
-
- opts |= O_NONBLOCK;
-
- if (fcntl(sockfd, F_SETFL, opts) < 0)
- {
- log_warn("fcntl() set socket options failure: %s\n", strerror(errno));
- return -1;
- }
-
- log_debug("Set socket[%d] none blocking\n", sockfd);
- return opts;
-}
-
-
-/* set socket receive and send buffer size in linux kernel space */
-int socket_set_buffer(int sockfd, int rsize, int ssize)
-{
- int opt;
- socklen_t optlen = sizeof(opt);
-
- if(sockfd < 0)
- return -1;
-
- /* Get system default receive buffer size, Linux X86: 85K */
- if (getsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, &optlen))
- {
- log_warn("getsockopt() get receive buffer failure: %s\n", strerror(errno));
- return -2;
- }
-
- /* Only when current receive buffer size larger than the default one will change it */
- if(rsize > opt)
- {
- opt = (int) rsize;
- if (setsockopt (sockfd, SOL_SOCKET, SO_RCVBUF, (char *) &opt, optlen))
- {
- log_warn("setsockopt() set receive buffer to %d failure: %s\n", opt, strerror(errno));
- return -2;
- }
- }
-
- /* Get system default send buffer size, Linux X86: 16K */
- if (getsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, &optlen))
- {
- log_warn("getsockopt() get send buffer failure: %s\n", strerror(errno));
- return -3;
- }
-
- /* Only when current receive buffer size larger than the default one will change it */
- if(ssize > opt)
- {
- opt = (int) ssize;
- if (setsockopt (sockfd, SOL_SOCKET, SO_SNDBUF, (char *) &opt, optlen))
- {
- log_warn("setsockopt() set send buffer to %d failure: %s\n", opt, strerror(errno));
- return -3;
- }
- }
-
- log_info("Set socket[%d] RCVBUF size:%d SNDBUF size:%d\n", sockfd, rsize, ssize);
- return 0;
-}
-
-/*
- * Enable socket SO_KEEPALIVE, if the connection disconnected, any system call on socket
- * will return immediately and errno will be set to "WSAENOTCONN"
- *
- * keepalive is not program related, but socket related, * so if you have multiple sockets,
- * you can handle keepalive for each of them separately.
- *
- * Reference: http://tldp.org/HOWTO/html_single/TCP-Keepalive-HOWTO/
- */
-int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt)
-{
- int opt;
-
- if(sockfd < 0)
- return -1;
-
- /* Enable the KEEPALIVE flag */
- opt = 1;
- if (setsockopt (sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof (opt)))
- {
- log_warn("setsockopt() enable SO_KEEPALIVE failure: %s\n", strerror(errno));
- return -2;
- }
-
- if(keepintvl || keepcnt)
- {
- /*
- * The tcp_keepidle parameter specifies the interval between the last data packet sent
- * (simple ACKs are not considered data) and the first keepalive probe; after the
- * connection is marked to need keepalive, this counter is not used any further.
- * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_time
- * 7200
- */
- opt = 3; /* 3 seconds */
- if (setsockopt (sockfd, SOL_TCP, TCP_KEEPIDLE, (char *) &opt, sizeof (opt)))
- {
- log_error("setsockopt() set TCP_KEEPIDLE to %d seconds failure: %s\n", opt, strerror(errno));
- return -3;
- }
-
- if((opt=keepintvl) > 0)
- {
- /*
- * The tcp_keepintvl parameter specifies the interval between subsequential keepalive
- * probes, regardless of what the connection has exchanged in the meantime.
- * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_intvl
- * 75
- */
- if (setsockopt (sockfd, SOL_TCP, TCP_KEEPINTVL, (char *) &opt, sizeof (opt)))
- {
- log_error("setsockopt() set TCP_KEEPINTVL to %d failure: %s\n", opt, strerror(errno));
- return -4;
- }
- }
-
- if((opt=keepcnt) > 0)
- {
- /*
- * The TCP_KEEPCNT option specifies the maximum number of unacknowledged probes to
- * send before considering the connection dead and notifying the application layer
- * probes to be sent. The value of TCP_KEEPCNT is an integer value between 1 and n,
- * where n is the value of the systemwide tcp_keepcnt parameter.
- * ~ >: cat /proc/sys/net/ipv4/tcp_keepalive_probes
- * 9
- */
- if (setsockopt (sockfd, SOL_TCP, TCP_KEEPCNT, (char *) &opt, sizeof (opt)))
- {
- log_error("setsockopt() set TCP_KEEPCNT to %d failure: %s\n", opt, strerror(errno));
- return -5;
- }
- }
- }
-
- log_debug("Set socket[%d] KEEPINTVL:%d KEEPCNT:%d\n", sockfd, keepintvl, keepcnt);
- return 0;
-}
-
-
-/* Set open file description count to max */
-void set_socket_rlimit(void)
-{
- struct rlimit limit = {0};
-
- getrlimit(RLIMIT_NOFILE, &limit );
- limit.rlim_cur = limit.rlim_max;
- setrlimit(RLIMIT_NOFILE, &limit );
-
- log_info("set socket open fd max count to %d\n", limit.rlim_max);
-}
-
diff --git a/project/socketd/booster/socket.h b/project/socketd/booster/socket.h
deleted file mode 100644
index dc41d69..0000000
--- a/project/socketd/booster/socket.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/********************************************************************************
- * Copyright: (C) 2022 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: socket.h
- * Description: This head file is for socket API functions
- *
- * Version: 1.0.0(18/04/22)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "18/04/22 17:09:59"
- *
- ********************************************************************************/
-
-#ifndef _SOCKET_H_
-#define _SOCKET_H_
-
-#define HOSTNAME_LEN 64
-
-typedef struct socket_ctx_s
-{
- char host[HOSTNAME_LEN]; /* CLIENT: Connect server hostname; SERVER: Unused */
- int port; /* CLIENT: Connect server port; SERVER: listen port */
- int fd; /* socket descriptor */
- int connected; /* socket connect status: 1->connected 0->disconnected */
-} socket_ctx_t;
-
-/* description: initial socket context
- * input args:
- * $sock: socket context pointer
- * $host: connect server hostname for client mode, unused for server mode
- * $port: connect server port for client mode or listen port for server mode
- * return value: <0: failure 0:ok
- */
-extern int socket_init(socket_ctx_t *sock, char *host, int port);
-
-/* description: close socket
- * input args:
- * $sock: socket context pointer
- * return value: <0: failure 0:ok
- */
-extern int socket_term(socket_ctx_t *sock);
-
-/* description: socket server start listen
- * input args:
- * $sock: socket context pointer
- * return value: <0: failure 0:ok
- */
-extern int socket_listen(socket_ctx_t *sock);
-
-/* description: check socket connect status
- * input args:
- * $sock: socket context pointer
- * return value: 1: connected 0:disconnected
- */
-extern int socket_connected(socket_ctx_t *sock);
-
-/* description: socket client connect to server
- * input args:
- * $sock: socket context pointer
- * return value: <0: failure 0:ok
- */
-extern int socket_connect(socket_ctx_t *sock);
-
-/* description: send data from the socket
- * input args:
- * $sock : socket context pointer
- * $data : socket send data
- * $bytes: socket send data bytes
- * return value: <0: failure 0:ok
- */
-extern int socket_send(socket_ctx_t *sock, char *data, int bytes);
-
-/* description: receive data from the socket
- * input args:
- * $sock : socket context pointer
- * $buf : socket receive data buffer
- * $size : socket receive data buffer size
- * $timeout: receive data time, <=0 will don't timeout
- * return value: <0: failure 0:ok
- */
-#define TIMEOUT_NONE 0
-extern int socket_recv(socket_ctx_t *sock, char *buf, int size, int timeout);
-
-/*+-------------------------------------------------------------------+
- *| socket utils function |
- *+-------------------------------------------------------------------+*/
-
-/* description: set socket listen port as reusable, fix port already used bug */
-extern int socket_set_reuseaddr(int sockfd);
-
-/* set socket as non-block mode, common socket default work as block mode */
-extern int socket_set_nonblock(int sockfd);
-
-/* set socket receive and send buffer size in linux kernel space */
-extern int socket_set_buffer(int sockfd, int rsize, int ssize);
-
-/* set heartbeat keepalive */
-extern int socket_set_keepalive(int sockfd, int keepintvl, int keepcnt);
-
-/* Set open file description count to max */
-extern void set_socket_rlimit(void);
-
-#endif /* ----- #ifndef _SOCKET_H_ ----- */
-
diff --git a/project/socketd/makefile b/project/socketd/makefile
deleted file mode 100644
index 0ff2b49..0000000
--- a/project/socketd/makefile
+++ /dev/null
@@ -1,67 +0,0 @@
-#********************************************************************************
-# Copyright: (C) 2023 LingYun IoT System Studio
-# All rights reserved.
-#
-# Filename: Makefile
-# Description: This file is the project top Makefie
-#
-# Version: 1.0.0(11/08/23)
-# Author: Guo Wenxue <guowenxue@gmail.com>
-# ChangeLog: 1, Release initial version on "11/08/23 16:18:43"
-#
-#*******************************************************************************
-
-PRJ_PATH=$(shell pwd)
-APP_NAME = sock_client
-
-BUILD_ARCH=$(shell uname -m)
-ifneq ($(findstring $(BUILD_ARCH), "x86_64" "i386"),)
- CROSS_COMPILE=arm-linux-gnueabihf-
-endif
-
-# C source files in top-level directory
-SRCFILES = $(wildcard *.c)
-
-# common CFLAGS for our source code
-CFLAGS = -Wall -Wshadow -Wundef -Wmaybe-uninitialized -D_GNU_SOURCE
-
-# sub-directory compiled to a library and need to link
-SRCS=booster
-SRCS_PATH=$(patsubst %,${PRJ_PATH}/%,$(SRCS))
-CFLAGS+=$(patsubst %,-I%,$(SRCS_PATH))
-LDFLAGS+=$(patsubst %,-L%,$(SRCS_PATH))
-LIBS=$(patsubst %,-l%,$(SRCS))
-LDFLAGS+=${LIBS}
-
-# Open source libraries
-CFLAGS+=-I ${PRJ_PATH}/sqlite/install/include
-LDFLAGS+=-L ${PRJ_PATH}/sqlite/install/lib
-LDFLAGS+=-lsqlite3
-LDFLAGS+=-lpthread
-
-# sub-directory need to entry and compile
-SUBDIR=sqlite ${SRCS}
-
-all: entry subdir
- ${CROSS_COMPILE}gcc ${CFLAGS} sock_client.c -o sock_client ${LDFLAGS}
-
-entry:
- @echo "Building ${APP_NAME} on ${BUILD_ARCH}"
-
-subdir:
- @for dir in ${SUBDIR} ; do if [ ! -e $${dir} ] ; then ln -s ../$${dir}; fi; done
- @for dir in ${SUBDIR} ; do make CFLAGS="${CFLAGS}" -C $${dir} ; done
-
-install:
- cp ${APP_NAME} /tftp
-
-clean:
- @for dir in ${SRCS} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done
- @rm -f ${APP_NAME}
-
-distclean:
- @for dir in ${SUBDIR} ; do if [ -e $${dir} ] ; then make clean -C $${dir}; fi; done
- @rm -f ${APP_NAME}
- @rm -f cscope.* tags
- @rm -f *.log *.db
-
diff --git a/project/socketd/sock_client.c b/project/socketd/sock_client.c
deleted file mode 100644
index 6a594d9..0000000
--- a/project/socketd/sock_client.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*********************************************************************************
- * Copyright: (C) 2019 LingYun IoT System Studio
- * All rights reserved.
- *
- * Filename: main.c
- * Description: This file
- *
- * Version: 1.0.0(29/01/19)
- * Author: Guo Wenxue <guowenxue@gmail.com>
- * ChangeLog: 1, Release initial version on "29/01/19 15:34:41"
- *
- ********************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <getopt.h>
-#include <libgen.h>
-#include <string.h>
-#include <errno.h>
-
-#include "logger.h"
-#include "ds18b20.h"
-#include "proc.h"
-#include "packet.h"
-#include "socket.h"
-#include "database.h"
-
-#define PROG_VERSION "v1.0.0"
-#define DAEMON_PIDFILE "/tmp/.socketd.pid"
-
-static void print_usage(char *progname)
-{
- printf("Usage: %s [OPTION]...\n", progname);
- printf(" %s is LingYun studio temperature socket client program running on RaspberryPi\n", progname);
-
- printf("\nMandatory arguments to long options are mandatory for short options too:\n");
- printf("-i(ipaddr) : sepcify server IP address\n");
- printf("-p(--port) : sepcify server port.\n");
- printf("-I(--interval): sepcify report time interval, default 60 seconds\n");
- printf("-d(--debug) : running in debug mode\n");
- printf("-h(--help) : display this help information\n");
- printf("-v(--version) : display the program version\n");
-
- printf("\n%s version %s\n", progname, PROG_VERSION);
- return;
-}
-
-int check_sample_time(time_t *last_time, int interval);
-
-int main (int argc, char **argv)
-{
- int daemon = 1;
- int rv;
-
- char *progname=NULL;
- char *logfile="sock_client.log";
- int loglevel=LOG_LEVEL_INFO;
- int logsize=10; /* logfile size max to 10K */
-
- char *serverip = NULL;
- int port = 0;
- int interval = 60; /* default report termperature every 60 seconds */
-
- socket_ctx_t sock;
- time_t last_time = 0;
- int sample_flag = 0;
-
- char pack_buf[1024];
- int pack_bytes = 0;
- pack_info_t pack_info;
- pack_proc_t pack_proc = packet_segmented_pack; /* use segmented string packet */
- //pack_proc_t pack_proc = packet_json_pack; /* use JSON string packet */
- //pack_proc_t pack_proc = packet_tlv_pack; /* use TLV(Tag Length Value) packet */
-
- struct option opts[] = {
- {"ipaddr", required_argument, NULL, 'i'},
- {"port", required_argument, NULL, 'p'},
- {"interval", required_argument, NULL, 'I'},
- {"debug", no_argument, NULL, 'd'},
- {"version", no_argument, NULL, 'v'},
- {"help", no_argument, NULL, 'h'},
- {NULL, 0, NULL, 0}
- };
-
- progname = (char *)basename(argv[0]);
-
- /* Parser the command line parameters */
- while( (rv=getopt_long(argc, argv, "i:p:I:dvh", opts, NULL)) != -1 )
- {
- switch (rv)
- {
- case 'i': /* set socket server hostname or IP address */
- serverip=optarg;
- break;
-
- case 'p': /* set socket server listen port */
- port=atoi(optarg);
- break;
-
- case 'I': /* set report time interval */
- interval=atoi(optarg);
- break;
-
-
- case 'd': /* set debug running */
- daemon = 0;
- logfile="console";
- loglevel=LOG_LEVEL_DEBUG;
- break;
-
- case 'v': /* get software version */
- printf("%s version %s\n", progname, PROG_VERSION);
- return 0;
-
- case 'h': /* get help information */
- print_usage(progname);
- return 0;
-
- default:
- break;
- }
-
- }
-
- if( !serverip || !port )
- {
- print_usage(argv[0]);
- return 0;
- }
-
- if( log_open(logfile, loglevel, logsize, THREAD_LOCK_NONE) < 0 )
- {
- fprintf(stderr, "Initial log system failed\n");
- return 1;
- }
-
- install_default_signal();
-
- if( check_set_program_running(daemon, DAEMON_PIDFILE) < 0 )
- goto cleanup;
-
- log_info("program start running.\n");
-
- if( database_init("sock_client.db") < 0 )
- {
- return 2;
- }
-
- socket_init(&sock, serverip, port);
-
- while( ! g_signal.stop )
- {
- /* +----------------------------------+
- * | check and sample temperature |
- * +----------------------------------+*/
-
- sample_flag = 0; /* clear sample flag */
-
- if( check_sample_time(&last_time, interval) )
- {
- log_debug("start DS18B20 sample termperature\n");
-
- if( (rv=ds18b20_get_temperature(&pack_info.temper)) < 0 )
- {
- log_error("DS18B20 sample temperature failure, rv=%d\n", rv);
- continue;
- }
- log_info("DS18B20 sample termperature %.3f oC\n", pack_info.temper);
-
- get_devid(pack_info.devid, sizeof(pack_info.devid), 88);
- get_time(&pack_info.sample_time);
-
- pack_bytes = pack_proc(&pack_info, (uint8_t *)pack_buf, sizeof(pack_buf));
- log_dump(LOG_LEVEL_DEBUG, NULL, pack_buf, pack_bytes);
-
- sample_flag = 1; /* set sample flag */
- }
-
- /* +---------------------------------+
- * | check and do socket connect |
- * +---------------------------------+*/
-
- /* start connect to server if not connected */
- if( !socket_connected(&sock) )
- {
- socket_connect(&sock);
- }
-
- /* +-------------------------------+
- * | socket disconnect |
- * +-------------------------------+*/
- if( !socket_connected(&sock) )
- {
- if( sample_flag )
- {
- database_push_packet(pack_buf, pack_bytes);
- }
-
- continue;
- }
-
- /* +-------------------------------+
- * | socket connected |
- * +-------------------------------+*/
-
- /* socket send sample packet */
- if( sample_flag )
- {
- log_debug("socket send sample packet bytes[%d]: %s\n", pack_bytes, pack_buf);
- if( socket_send(&sock, pack_buf, pack_bytes) < 0 )
- {
- log_warn("socket send sample packet failure, save it in database now.\n");
- database_push_packet(pack_buf, pack_bytes);
- continue;
- }
- }
-
- /* socket send packet in database */
- if( !database_pop_packet(pack_buf, sizeof(pack_buf), &pack_bytes) )
- {
- log_debug("socket send database packet bytes[%d]: %s\n", pack_bytes, pack_buf);
- if( socket_send(&sock, pack_buf, pack_bytes) < 0 )
- {
- log_error("socket send database packet failure");
- continue;
- }
- else
- {
- log_warn("socket send database packet okay, remove it from database now.\n");
- database_del_packet();
- }
- }
-
- msleep(5);
- }
-
-cleanup:
- socket_term(&sock);
- database_term();
- unlink(DAEMON_PIDFILE);
- log_close();
-
- return 0;
-}
-
-int check_sample_time(time_t *last_time, int interval)
-{
- int need = 0; /* no need sample now */
- time_t now;
-
- time(&now);
-
- if( difftime(now, *last_time)>interval )
- {
- need = 1; /* need sample now */
- *last_time = now;
- }
-
- return need;
-}
diff --git a/project/socketd/sqlite/build.sh b/project/socketd/sqlite/build.sh
deleted file mode 100755
index 53599b4..0000000
--- a/project/socketd/sqlite/build.sh
+++ /dev/null
@@ -1,181 +0,0 @@
-#!/bin/bash
-
-# library name and version
-# Official: https://www.sqlite.org/index.html
-LIB_NAME=sqlite-autoconf-3430000
-PACK_SUFIX=tar.gz
-
-# LingYun source code FTP server
-LY_FTP=http://main.iot-yun.club:2211/src/
-
-# library download URL address
-LIB_URL=$LY_FTP
-
-# Cross compiler for cross compile on Linux server
-CROSS_COMPILE=arm-linux-gnueabihf-
-
-# compile jobs
-JOBS=`cat /proc/cpuinfo |grep "processor"|wc -l`
-
-# this project absolute path
-PRJ_PATH=$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)
-
-# top project absolute path
-TOP_PATH=$(realpath $PRJ_PATH/..)
-
-# binaries install path
-PREFIX_PATH=$PRJ_PATH/install
-BIN_PATH=$PREFIX_PATH/bin
-LIB_PATH=$PREFIX_PATH/lib
-INC_PATH=$PREFIX_PATH/include
-
-# check installed or not file
-INST_FILE=$PREFIX_PATH/bin/sqlite3
-
-# shell script will exit once get command error
-set -e
-
-#+-------------------------+
-#| Shell script functions |
-#+-------------------------+
-
-function pr_error() {
- echo -e "\033[40;31m $1 \033[0m"
-}
-
-function pr_warn() {
- echo -e "\033[40;33m $1 \033[0m"
-}
-
-function pr_info() {
- echo -e "\033[40;32m $1 \033[0m"
-}
-
-function check_result()
-{
- if [ $? != 0 ] ; then
- pr_error $1
- fi
-}
-# decompress a packet to destination path
-function do_unpack()
-{
- tarball=$1
- dstpath=`pwd`
-
- if [[ $# == 2 ]] ; then
- dstpath=$2
- fi
-
- pr_info "decompress $tarball => $dstpath"
-
- mkdir -p $dstpath
- case $tarball in
- *.tar.gz)
- tar -xzf $tarball -C $dstpath
- ;;
-
- *.tar.bz2)
- tar -xjf $tarball -C $dstpath
- ;;
-
- *.tar.xz)
- tar -xJf $tarball -C $dstpath
- ;;
-
- *.tar.zst)
- tar -I zstd -xf $tarball -C $dstpath
- ;;
-
- *.tar)
- tar -xf $tarball -C $dstpath
- ;;
-
- *.zip)
- unzip -qo $tarball -d $dstpath
- ;;
-
- *)
- pr_error "decompress Unsupport packet: $tarball"
- return 1;
- ;;
- esac
-}
-
-function do_export()
-{
- BUILD_ARCH=$(uname -m)
- if [[ $BUILD_ARCH =~ "arm" ]] ; then
- pr_warn "local($BUILD_ARCH) compile $LIB_NAME"
- return ;
- fi
-
- pr_warn "cross(${CROSS_COMPILE}) compile $LIB_NAME"
-
- # export cross toolchain
- export CC=${CROSS_COMPILE}gcc
- export CXX=${CROSS_COMPILE}g++
- export AS=${CROSS_COMPILE}as
- export AR=${CROSS_COMPILE}ar
- export LD=${CROSS_COMPILE}ld
- export NM=${CROSS_COMPILE}nm
- export RANLIB=${CROSS_COMPILE}ranlib
- export OBJDUMP=${CROSS_COMPILE}objdump
- export STRIP=${CROSS_COMPILE}strip
-
- # export cross configure
- export CONFIG_CROSS=" --build=i686-pc-linux --host=arm-linux "
-
- # Clear LDFLAGS and CFLAGS
- export LDFLAGS=
- export CFLAGS=
-}
-
-function do_fetch()
-{
- if [ -e ${INST_FILE} ] ; then
- pr_warn "$LIB_NAME compile and installed alredy"
- exit ;
- fi
-
- if [ -d $LIB_NAME ] ; then
- pr_warn "$LIB_NAME fetch already"
- return ;
- fi
-
- if [ ! -f ${LIB_NAME}.${PACK_SUFIX} ] ; then
- wget ${LIB_URL}/${LIB_NAME}.${PACK_SUFIX}
- check_result "ERROR: download ${LIB_NAME} failure"
- fi
-
- do_unpack ${LIB_NAME}.${PACK_SUFIX}
-}
-
-function do_build()
-{
- cd $LIB_NAME
-
- do_export
-
- ./configure --prefix=${PREFIX_PATH} ${CONFIG_CROSS} --enable-static --enable-static-shell
- check_result "ERROR: configure ${LIB_NAME} failure"
-
- make && make install
- check_result "ERROR: compile ${LIB_NAME} failure"
-}
-
-function do_clean()
-{
- rm -rf *${LIB_NAME}*
-}
-
-if [[ $# == 1 && $1 == -c ]] ;then
- pr_warn "start clean ${LIB_NAME}"
- do_clean
- exit;
-fi
-
-do_fetch
-
-do_build
-
diff --git a/project/socketd/sqlite/makefile b/project/socketd/sqlite/makefile
deleted file mode 100644
index 4572f9f..0000000
--- a/project/socketd/sqlite/makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-
-all:
- ./build.sh
-
-clean:
- rm -rf install
- ./build.sh -c
diff --git a/modules/at24c.c b/utils/at24c.c
similarity index 100%
rename from modules/at24c.c
rename to utils/at24c.c
diff --git a/modules/diagram/AT24C256.kvdat b/utils/diagram/AT24C256.kvdat
similarity index 100%
rename from modules/diagram/AT24C256.kvdat
rename to utils/diagram/AT24C256.kvdat
Binary files differ
diff --git a/modules/diagram/SHT20.kvdat b/utils/diagram/SHT20.kvdat
similarity index 100%
rename from modules/diagram/SHT20.kvdat
rename to utils/diagram/SHT20.kvdat
Binary files differ
diff --git a/modules/ds18b20.c b/utils/ds18b20.c
similarity index 100%
rename from modules/ds18b20.c
rename to utils/ds18b20.c
diff --git a/modules/infrared.c b/utils/infrared.c
similarity index 100%
rename from modules/infrared.c
rename to utils/infrared.c
diff --git a/modules/leds.c b/utils/leds.c
similarity index 100%
rename from modules/leds.c
rename to utils/leds.c
diff --git a/modules/makefile b/utils/makefile
similarity index 100%
rename from modules/makefile
rename to utils/makefile
diff --git a/modules/pwm.c b/utils/pwm.c
similarity index 100%
rename from modules/pwm.c
rename to utils/pwm.c
diff --git a/modules/relay.c b/utils/relay.c
similarity index 100%
rename from modules/relay.c
rename to utils/relay.c
diff --git a/modules/sht20.c b/utils/sht20.c
similarity index 100%
rename from modules/sht20.c
rename to utils/sht20.c
diff --git a/modules/tsl2561.c b/utils/tsl2561.c
similarity index 100%
rename from modules/tsl2561.c
rename to utils/tsl2561.c
diff --git a/modules/w25qflash.c b/utils/w25qflash.c
similarity index 100%
rename from modules/w25qflash.c
rename to utils/w25qflash.c
diff --git a/modules/w25qflash.h b/utils/w25qflash.h
similarity index 100%
rename from modules/w25qflash.h
rename to utils/w25qflash.h
--
Gitblit v1.9.1