Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Add SenML JSON support.
The media type replaces supportJSON in lwm2m_client_t to allow for TLV,
JSON, or SenML JSON. Easily extended for SenML CBOR and others in the
future.

const added to some pointer arguments where functions don't modify what
is pointed to.

Added base64 decoding to support opaque data types.

Added functions for going between text and objLink.

Signed-off-by: Scott Bertin <sbertin@telular.com>
  • Loading branch information
sbertin-telular committed Feb 19, 2019
1 parent 2a0d6c5 commit 92e9e12
Show file tree
Hide file tree
Showing 23 changed files with 3,006 additions and 220 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -39,6 +39,7 @@ Several compilation switches are used:
- LWM2M_BOOTSTRAP_SERVER_MODE to enable LWM2M Bootstrap Server interfaces.
- LWM2M_BOOTSTRAP to enable LWM2M Bootstrap support in a LWM2M Client.
- LWM2M_SUPPORT_JSON to enable JSON payload support (implicit when defining LWM2M_SERVER_MODE)
- LWM2M_SUPPORT_SENML_JSON to enable SenML JSON payload support (implicit for LWM2M 1.1 or greater when defining LWM2M_SERVER_MODE or LWM2M_BOOTSTRAP_SERVER_MODE)
- LWM2M_OLD_CONTENT_FORMAT_SUPPORT to support the deprecated content format values for TLV and JSON.
- LWM2M_VERSION to specify which version of the LWM2M spec to support.
Clients will support only that version. Servers will support that version and below.
Expand Down
20 changes: 16 additions & 4 deletions core/data.c
Expand Up @@ -139,7 +139,7 @@ static int prv_textSerialize(lwm2m_data_t * dataP,
}

static int prv_setBuffer(lwm2m_data_t * dataP,
uint8_t * buffer,
const uint8_t * buffer,
size_t bufferLen)
{
dataP->value.asBuffer.buffer = (uint8_t *)lwm2m_malloc(bufferLen);
Expand Down Expand Up @@ -242,7 +242,7 @@ void lwm2m_data_encode_string(const char * string,
}
}

void lwm2m_data_encode_opaque(uint8_t * buffer,
void lwm2m_data_encode_opaque(const uint8_t * buffer,
size_t length,
lwm2m_data_t * dataP)
{
Expand Down Expand Up @@ -642,7 +642,7 @@ void lwm2m_data_encode_instances(lwm2m_data_t * subDataP,
}

int lwm2m_data_parse(lwm2m_uri_t * uriP,
uint8_t * buffer,
const uint8_t * buffer,
size_t bufferLen,
lwm2m_media_type_t format,
lwm2m_data_t ** dataP)
Expand Down Expand Up @@ -703,6 +703,11 @@ int lwm2m_data_parse(lwm2m_uri_t * uriP,
return json_parse(uriP, buffer, bufferLen, dataP);
#endif

#ifdef LWM2M_SUPPORT_SENML_JSON
case LWM2M_CONTENT_SENML_JSON:
return senml_json_parse(uriP, buffer, bufferLen, dataP);
#endif

default:
return 0;
}
Expand All @@ -727,7 +732,9 @@ int lwm2m_data_serialize(lwm2m_uri_t * uriP,
|| dataP->type == LWM2M_TYPE_OBJECT_INSTANCE
|| dataP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
{
#ifdef LWM2M_SUPPORT_JSON
#ifdef LWM2M_SUPPORT_SENML_JSON
*formatP = LWM2M_CONTENT_SENML_JSON;
#elif defined(LWM2M_SUPPORT_JSON)
*formatP = LWM2M_CONTENT_JSON;
#else
*formatP = LWM2M_CONTENT_TLV;
Expand Down Expand Up @@ -794,6 +801,11 @@ int lwm2m_data_serialize(lwm2m_uri_t * uriP,
return json_serialize(uriP, size, dataP, bufferP);
#endif

#ifdef LWM2M_SUPPORT_SENML_JSON
case LWM2M_CONTENT_SENML_JSON:
return senml_json_serialize(uriP, size, dataP, bufferP);
#endif

default:
return -1;
}
Expand Down
93 changes: 67 additions & 26 deletions core/internals.h
Expand Up @@ -106,13 +106,14 @@
((S) == STATE_BS_FAILING ? "STATE_BS_FAILING" : \
((S) == STATE_BS_FAILED ? "STATE_BS_FAILED" : \
"Unknown"))))))))))))))))
#define STR_MEDIA_TYPE(M) \
((M) == LWM2M_CONTENT_TEXT ? "LWM2M_CONTENT_TEXT" : \
((M) == LWM2M_CONTENT_LINK ? "LWM2M_CONTENT_LINK" : \
((M) == LWM2M_CONTENT_OPAQUE ? "LWM2M_CONTENT_OPAQUE" : \
((M) == LWM2M_CONTENT_TLV ? "LWM2M_CONTENT_TLV" : \
((M) == LWM2M_CONTENT_JSON ? "LWM2M_CONTENT_JSON" : \
"Unknown")))))
#define STR_MEDIA_TYPE(M) \
((M) == LWM2M_CONTENT_TEXT ? "LWM2M_CONTENT_TEXT" : \
((M) == LWM2M_CONTENT_LINK ? "LWM2M_CONTENT_LINK" : \
((M) == LWM2M_CONTENT_OPAQUE ? "LWM2M_CONTENT_OPAQUE" : \
((M) == LWM2M_CONTENT_TLV ? "LWM2M_CONTENT_TLV" : \
((M) == LWM2M_CONTENT_JSON ? "LWM2M_CONTENT_JSON" : \
((M) == LWM2M_CONTENT_SENML_JSON ? "LWM2M_CONTENT_SENML_JSON" : \
"Unknown"))))))
#define STR_STATE(S) \
((S) == STATE_INITIAL ? "STATE_INITIAL" : \
((S) == STATE_BOOTSTRAP_REQUIRED ? "STATE_BOOTSTRAP_REQUIRED" : \
Expand All @@ -129,7 +130,10 @@

#define LWM2M_DEFAULT_LIFETIME 86400

#ifdef LWM2M_SUPPORT_JSON
#ifdef LWM2M_SUPPORT_SENML_JSON
#define REG_LWM2M_RESOURCE_TYPE ">;rt=\"oma.lwm2m\";ct=110,"
#define REG_LWM2M_RESOURCE_TYPE_LEN 23
#elif defined(LWM2M_SUPPORT_JSON)
#define REG_LWM2M_RESOURCE_TYPE ">;rt=\"oma.lwm2m\";ct=11543,"
#define REG_LWM2M_RESOURCE_TYPE_LEN 25
#else
Expand Down Expand Up @@ -178,19 +182,23 @@
#define QUERY_VERSION_FULL QUERY_VERSION LWM2M_VERSION
#define QUERY_VERSION_FULL_LEN QUERY_VERSION_LEN+LWM2M_VERSION_LEN

#define REG_URI_START '<'
#define REG_URI_END '>'
#define REG_DELIMITER ','
#define REG_ATTR_SEPARATOR ';'
#define REG_ATTR_EQUALS '='
#define REG_ATTR_TYPE_KEY "rt"
#define REG_ATTR_TYPE_KEY_LEN 2
#define REG_ATTR_TYPE_VALUE "\"oma.lwm2m\""
#define REG_ATTR_TYPE_VALUE_LEN 11
#define REG_ATTR_CONTENT_KEY "ct"
#define REG_ATTR_CONTENT_KEY_LEN 2
#define REG_ATTR_CONTENT_JSON "11543" // Temporary value
#define REG_ATTR_CONTENT_JSON_LEN 5
#define REG_URI_START '<'
#define REG_URI_END '>'
#define REG_DELIMITER ','
#define REG_ATTR_SEPARATOR ';'
#define REG_ATTR_EQUALS '='
#define REG_ATTR_TYPE_KEY "rt"
#define REG_ATTR_TYPE_KEY_LEN 2
#define REG_ATTR_TYPE_VALUE "\"oma.lwm2m\""
#define REG_ATTR_TYPE_VALUE_LEN 11
#define REG_ATTR_CONTENT_KEY "ct"
#define REG_ATTR_CONTENT_KEY_LEN 2
#define REG_ATTR_CONTENT_JSON "11543"
#define REG_ATTR_CONTENT_JSON_LEN 5
#define REG_ATTR_CONTENT_JSON_OLD "1543"
#define REG_ATTR_CONTENT_JSON_OLD_LEN 4
#define REG_ATTR_CONTENT_SENML_JSON "110"
#define REG_ATTR_CONTENT_SENML_JSON_LEN 3

#define ATTR_SERVER_ID_STR "ep="
#define ATTR_SERVER_ID_LEN 3
Expand Down Expand Up @@ -327,15 +335,38 @@ void bootstrap_start(lwm2m_context_t * contextP);
lwm2m_status_t bootstrap_getStatus(lwm2m_context_t * contextP);

// defined in tlv.c
int tlv_parse(uint8_t * buffer, size_t bufferLen, lwm2m_data_t ** dataP);
int tlv_parse(const uint8_t * buffer, size_t bufferLen, lwm2m_data_t ** dataP);
int tlv_serialize(bool isResourceInstance, int size, lwm2m_data_t * dataP, uint8_t ** bufferP);

// defined in json.c
#ifdef LWM2M_SUPPORT_JSON
int json_parse(lwm2m_uri_t * uriP, uint8_t * buffer, size_t bufferLen, lwm2m_data_t ** dataP);
int json_parse(lwm2m_uri_t * uriP, const uint8_t * buffer, size_t bufferLen, lwm2m_data_t ** dataP);
int json_serialize(lwm2m_uri_t * uriP, int size, lwm2m_data_t * tlvP, uint8_t ** bufferP);
#endif

// defined in senml_json.c
#ifdef LWM2M_SUPPORT_SENML_JSON
int senml_json_parse(const lwm2m_uri_t * uriP, const uint8_t * buffer, size_t bufferLen, lwm2m_data_t ** dataP);
int senml_json_serialize(const lwm2m_uri_t * uriP, int size, const lwm2m_data_t * tlvP, uint8_t ** bufferP);
#endif

// defined in json_common.c
#if defined(LWM2M_SUPPORT_JSON) || defined(LWM2M_SUPPORT_SENML_JSON)
size_t json_skipSpace(const uint8_t * buffer,size_t bufferLen);
int json_split(const uint8_t * buffer, size_t bufferLen, size_t * tokenStartP, size_t * tokenLenP, size_t * valueStartP, size_t * valueLenP);
int json_itemLength(const uint8_t * buffer, size_t bufferLen);
int json_countItems(const uint8_t * buffer, size_t bufferLen);
int json_convertNumeric(const uint8_t *value, size_t valueLen, lwm2m_data_t *targetP);
int json_convertTime(const uint8_t *valueStart, size_t valueLen, time_t *t);
size_t json_unescapeString(uint8_t *dst, const uint8_t *src, size_t len);
size_t json_escapeString(uint8_t *dst, size_t dstLen, const uint8_t *src, size_t srcLen);
lwm2m_data_t * json_extendData(lwm2m_data_t * parentP);
int json_dataStrip(int size, lwm2m_data_t * dataP, lwm2m_data_t ** resultP);
lwm2m_data_t * json_findDataItem(lwm2m_data_t * listP, size_t count, uint16_t id);
uri_depth_t json_decreaseLevel(uri_depth_t level);
int json_findAndCheckData(const lwm2m_uri_t * uriP, uri_depth_t level, size_t size, const lwm2m_data_t * tlvP, lwm2m_data_t ** targetP);
#endif

// defined in discover.c
int discover_serialize(lwm2m_context_t * contextP, lwm2m_uri_t * uriP, lwm2m_server_t * serverP, int size, lwm2m_data_t * dataP, uint8_t ** bufferP);

Expand All @@ -353,12 +384,22 @@ int utils_stringCopy(char * buffer, size_t length, const char * str);
size_t utils_intToText(int64_t data, uint8_t * string, size_t length);
size_t utils_uintToText(uint64_t data, uint8_t * string, size_t length);
size_t utils_floatToText(double data, uint8_t * string, size_t length);
int utils_textToInt(uint8_t * buffer, int length, int64_t * dataP);
size_t utils_objLinkToText(uint16_t objectId,
uint16_t objectInstanceId,
uint8_t * string,
size_t length);
int utils_textToInt(const uint8_t * buffer, int length, int64_t * dataP);
int utils_textToUInt(const uint8_t * buffer, int length, uint64_t * dataP);
int utils_textToFloat(uint8_t * buffer, int length, double * dataP);
int utils_textToFloat(const uint8_t * buffer, int length, double * dataP);
int utils_textToObjLink(const uint8_t * buffer,
int length,
uint16_t * objectId,
uint16_t * objectInstanceId);
void utils_copyValue(void * dst, const void * src, size_t len);
size_t utils_base64GetSize(size_t dataLen);
size_t utils_base64Encode(uint8_t * dataP, size_t dataLen, uint8_t * bufferP, size_t bufferLen);
size_t utils_base64Encode(const uint8_t * dataP, size_t dataLen, uint8_t * bufferP, size_t bufferLen);
size_t utils_base64GetDecodedSize(const char * dataP, size_t dataLen);
size_t utils_base64Decode(const char * dataP, size_t dataLen, uint8_t * bufferP, size_t bufferLen);
#ifdef LWM2M_CLIENT_MODE
lwm2m_server_t * utils_findServer(lwm2m_context_t * contextP, void * fromSessionH);
lwm2m_server_t * utils_findBootstrapServer(lwm2m_context_t * contextP, void * fromSessionH);
Expand Down
28 changes: 14 additions & 14 deletions core/json.c
Expand Up @@ -90,10 +90,10 @@ typedef enum

typedef struct
{
uint16_t ids[4];
_type type;
uint8_t * value;
size_t valueLen;
uint16_t ids[4];
_type type;
const uint8_t * value;
size_t valueLen;
} _record_t;

static int prv_isReserved(char sign)
Expand Down Expand Up @@ -125,7 +125,7 @@ static int prv_isWhiteSpace(uint8_t sign)
return 0;
}

static size_t prv_skipSpace(uint8_t * buffer,
static size_t prv_skipSpace(const uint8_t * buffer,
size_t bufferLen)
{
size_t i;
Expand All @@ -140,7 +140,7 @@ static size_t prv_skipSpace(uint8_t * buffer,
return i;
}

static int prv_split(uint8_t * buffer,
static int prv_split(const uint8_t * buffer,
size_t bufferLen,
int * tokenStartP,
int * tokenLenP,
Expand Down Expand Up @@ -237,7 +237,7 @@ static int prv_split(uint8_t * buffer,
return (int)index;
}

static int prv_countItems(uint8_t * buffer,
static int prv_countItems(const uint8_t * buffer,
size_t bufferLen)
{
int count;
Expand Down Expand Up @@ -285,7 +285,7 @@ static int prv_countItems(uint8_t * buffer,
return -1;
}

static int prv_parseItem(uint8_t * buffer,
static int prv_parseItem(const uint8_t * buffer,
size_t bufferLen,
_record_t * recordP)
{
Expand Down Expand Up @@ -757,7 +757,7 @@ static int prv_dataStrip(int size,
}

int json_parse(lwm2m_uri_t * uriP,
uint8_t * buffer,
const uint8_t * buffer,
size_t bufferLen,
lwm2m_data_t ** dataP)
{
Expand Down Expand Up @@ -1166,11 +1166,11 @@ static int prv_serializeValue(lwm2m_data_t * tlvP,
return head;
}

int prv_serializeData(lwm2m_data_t * tlvP,
uint8_t * parentUriStr,
size_t parentUriLen,
uint8_t * buffer,
size_t bufferLen)
static int prv_serializeData(lwm2m_data_t * tlvP,
const uint8_t * parentUriStr,
size_t parentUriLen,
uint8_t * buffer,
size_t bufferLen)
{
int head;
int res;
Expand Down

0 comments on commit 92e9e12

Please sign in to comment.