Skip to content

Commit

Permalink
Fix several JSON and SenML JSON issues.
Browse files Browse the repository at this point in the history
Fix problem serializing resource instance reads.
Fix handling of empty strings and opaque.
Fix JSON serializing single instance resource as multiple. Fixes eclipse-wakaama#378.
Fix JSON parsing of multiple instance resources. Fixes eclipse-wakaama#399.

Signed-off-by: Scott Bertin <sbertin@telular.com>
  • Loading branch information
sbertin-telular committed Mar 11, 2019
1 parent dda6a20 commit dc94e44
Show file tree
Hide file tree
Showing 6 changed files with 188 additions and 103 deletions.
2 changes: 1 addition & 1 deletion core/internals.h
Expand Up @@ -364,7 +364,7 @@ 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);
int json_findAndCheckData(const lwm2m_uri_t * uriP, uri_depth_t baseLevel, size_t size, const lwm2m_data_t * tlvP, lwm2m_data_t ** targetP, uri_depth_t *targetLevelP);
#endif

// defined in discover.c
Expand Down
37 changes: 21 additions & 16 deletions core/json.c
Expand Up @@ -651,6 +651,10 @@ int json_parse(lwm2m_uri_t * uriP,
}
else
{
/* Base name may have a trailing "/" on a multiple instance
* resource. This isn't valid for a URI string in LWM2M 1.0.
* Strip off any trailing "/" to avoid an error. */
if (buffer[bnStart + bnLen - 1] == '/') bnLen -= 1;
res = lwm2m_stringToUri((char *)buffer + bnStart, bnLen, &baseURI);
if (res < 0 || (size_t)res != bnLen) goto error;
baseUriP = &baseURI;
Expand Down Expand Up @@ -699,18 +703,10 @@ int json_parse(lwm2m_uri_t * uriP,
targetP = resultP + i;
if (targetP->id == uriP->resourceId)
{
if (targetP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
{
resP = targetP->value.asChildren.array;
size = targetP->value.asChildren.count;
}
else
{
size = json_dataStrip(1, targetP, &resP);
if (size <= 0) goto error;
lwm2m_data_free(count, parsedP);
parsedP = NULL;
}
size = json_dataStrip(1, targetP, &resP);
if (size <= 0) goto error;
lwm2m_data_free(count, parsedP);
parsedP = NULL;
}
}
if (resP == NULL) goto error;
Expand Down Expand Up @@ -773,7 +769,7 @@ static int prv_serializeValue(lwm2m_data_t * tlvP,
bufferLen - head,
tlvP->value.asBuffer.buffer,
tlvP->value.asBuffer.length);
if (!res) return -1;
if (tlvP->value.asBuffer.length != 0 && res == 0) return -1;
head += res;

if (bufferLen - head < JSON_ITEM_STRING_END_SIZE) return -1;
Expand Down Expand Up @@ -984,6 +980,7 @@ int json_serialize(lwm2m_uri_t * uriP,
uint8_t baseUriStr[URI_MAX_STRING_LEN];
int baseUriLen;
uri_depth_t rootLevel;
uri_depth_t baseLevel;
int num;
lwm2m_data_t * targetP;
const uint8_t *parentUriStr = NULL;
Expand All @@ -1007,13 +1004,21 @@ int json_serialize(lwm2m_uri_t * uriP,
}
#endif

baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &rootLevel);
baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, &baseLevel);
if (baseUriLen < 0) return -1;
rootLevel = json_decreaseLevel(rootLevel);

num = json_findAndCheckData(uriP, rootLevel, size, tlvP, &targetP);
num = json_findAndCheckData(uriP, baseLevel, size, tlvP, &targetP, &rootLevel);
if (num < 0) return -1;

if (baseLevel >= URI_DEPTH_RESOURCE
&& rootLevel == baseLevel
&& baseUriLen > 1)
{
/* Remove the ID from the base name */
while (baseUriLen > 1 && baseUriStr[baseUriLen - 1] != '/') baseUriLen--;
if (baseUriLen > 1 && baseUriStr[baseUriLen - 1] == '/') baseUriLen--;
}

while (num == 1
&& (targetP->type == LWM2M_TYPE_OBJECT
|| targetP->type == LWM2M_TYPE_OBJECT_INSTANCE
Expand Down
109 changes: 73 additions & 36 deletions core/json_common.c
Expand Up @@ -598,11 +598,12 @@ 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)
static int prv_findAndCheckData(const lwm2m_uri_t * uriP,
uri_depth_t desiredLevel,
size_t size,
const lwm2m_data_t * tlvP,
lwm2m_data_t ** targetP,
uri_depth_t *targetLevelP)
{
size_t index;
int result;
Expand Down Expand Up @@ -639,12 +640,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,

*targetP = NULL;
result = -1;
switch (level)
switch (desiredLevel)
{
case URI_DEPTH_OBJECT:
if (tlvP[0].type == LWM2M_TYPE_OBJECT)
{
*targetP = (lwm2m_data_t*)tlvP;
*targetLevelP = URI_DEPTH_OBJECT;
result = (int)size;
}
break;
Expand All @@ -657,11 +659,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->objectId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_OBJECT_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -682,11 +686,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->objectId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_OBJECT_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -695,11 +701,12 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->instanceId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_RESOURCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP, targetLevelP);
}
}
break;
Expand All @@ -718,11 +725,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->objectId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_OBJECT_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -731,11 +740,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->instanceId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_RESOURCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -744,11 +755,13 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
{
if (tlvP[index].id == uriP->resourceId)
{
return json_findAndCheckData(uriP,
level,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP);
*targetLevelP = URI_DEPTH_RESOURCE_INSTANCE;
return prv_findAndCheckData(uriP,
desiredLevel,
tlvP[index].value.asChildren.count,
tlvP[index].value.asChildren.array,
targetP,
targetLevelP);
}
}
break;
Expand All @@ -766,4 +779,28 @@ int json_findAndCheckData(const lwm2m_uri_t * uriP,
return result;
}

int json_findAndCheckData(const lwm2m_uri_t * uriP,
uri_depth_t baseLevel,
size_t size,
const lwm2m_data_t * tlvP,
lwm2m_data_t ** targetP,
uri_depth_t *targetLevelP)
{
uri_depth_t desiredLevel = json_decreaseLevel(baseLevel);
if (baseLevel < URI_DEPTH_RESOURCE)
{
*targetLevelP = desiredLevel;
}
else
{
*targetLevelP = baseLevel;
}
return prv_findAndCheckData(uriP,
desiredLevel,
size,
tlvP,
targetP,
targetLevelP);
}

#endif
52 changes: 8 additions & 44 deletions core/senml_json.c
Expand Up @@ -805,7 +805,7 @@ static int prv_serializeValue(const lwm2m_data_t * tlvP,
bufferLen - head,
tlvP->value.asBuffer.buffer,
tlvP->value.asBuffer.length);
if (!res) return -1;
if (res < tlvP->value.asBuffer.length) return -1;
head += res;

if (bufferLen - head < 1) return -1;
Expand Down Expand Up @@ -897,7 +897,7 @@ static int prv_serializeValue(const lwm2m_data_t * tlvP,
tlvP->value.asBuffer.length,
buffer+head,
bufferLen - head);
if (!res) return -1;
if (res < tlvP->value.asBuffer.length) return -1;
head += res;
}

Expand Down Expand Up @@ -946,22 +946,6 @@ static int prv_serializeData(const lwm2m_data_t * tlvP,

head = 0;

/* Check to override passed in level */
switch (tlvP->type)
{
case LWM2M_TYPE_MULTIPLE_RESOURCE:
level = URI_DEPTH_RESOURCE;
break;
case LWM2M_TYPE_OBJECT:
level = URI_DEPTH_OBJECT;
break;
case LWM2M_TYPE_OBJECT_INSTANCE:
level = URI_DEPTH_OBJECT_INSTANCE;
break;
default:
break;
}

switch (tlvP->type)
{
case LWM2M_TYPE_MULTIPLE_RESOURCE:
Expand Down Expand Up @@ -1108,35 +1092,15 @@ int senml_json_serialize(const lwm2m_uri_t * uriP,
baseUriStr[baseUriLen++] = '/';
}

num = json_findAndCheckData(uriP, json_decreaseLevel(baseLevel), size, tlvP, &targetP);
num = json_findAndCheckData(uriP, baseLevel, size, tlvP, &targetP, &rootLevel);
if (num < 0) return -1;

switch (tlvP->type)
if (baseLevel < rootLevel
&& baseUriLen > 1
&& baseUriStr[baseUriLen - 1] != '/')
{
case LWM2M_TYPE_OBJECT:
rootLevel = URI_DEPTH_OBJECT;
break;
case LWM2M_TYPE_OBJECT_INSTANCE:
rootLevel = URI_DEPTH_OBJECT_INSTANCE;
break;
case LWM2M_TYPE_MULTIPLE_RESOURCE:
if (baseUriLen > 1 && baseUriStr[baseUriLen - 1] != '/')
{
if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0;
baseUriStr[baseUriLen++] = '/';
}
rootLevel = URI_DEPTH_RESOURCE_INSTANCE;
break;
default:
if (baseLevel == URI_DEPTH_RESOURCE_INSTANCE)
{
rootLevel = URI_DEPTH_RESOURCE_INSTANCE;
}
else
{
rootLevel = URI_DEPTH_RESOURCE;
}
break;
if (baseUriLen >= URI_MAX_STRING_LEN -1) return 0;
baseUriStr[baseUriLen++] = '/';
}

if (!baseUriLen || baseUriStr[baseUriLen - 1] != '/')
Expand Down

0 comments on commit dc94e44

Please sign in to comment.