Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support object versions #545

Merged
merged 1 commit into from
Feb 24, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions core/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@

#define REG_OBJECT_MIN_LEN 5 // "</n>,"
#define REG_PATH_END ">,"
#define REG_VERSION_START ">;ver="
#define REG_PATH_SEPARATOR "/"

#define REG_OBJECT_PATH "<%s/%hu>,"
Expand Down Expand Up @@ -220,6 +221,8 @@
#define ATTR_STEP_LEN 3
#define ATTR_DIMENSION_STR "dim="
#define ATTR_DIMENSION_LEN 4
#define ATTR_VERSION_STR "ver="
#define ATTR_VERSION_LEN 4

#ifdef LWM2M_VERSION_1_0
#define URI_MAX_STRING_LEN 18 // /65535/65535/65535
Expand Down
63 changes: 59 additions & 4 deletions core/objects.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,12 +815,36 @@ int object_getRegisterPayloadBufferLength(lwm2m_context_t * contextP)
length = result;
index += length;

if (objectP->instanceList == NULL)
if (objectP->versionMajor != 0 || objectP->versionMinor != 0)
{
index -= 1;
index += strlen(REG_VERSION_START);

result = utils_uintToText(objectP->versionMajor, buffer, sizeof(buffer));
if (result < 0) return 0;
index += result;

index += 1;

result = utils_uintToText(objectP->versionMinor, buffer, sizeof(buffer));
if (result < 0) return 0;
index += result;

index += 1;

if(objectP->instanceList != NULL)
{
start = index;
index += length;
}
}
else if(objectP->instanceList == NULL)
{
index -= 1;
index += strlen(REG_PATH_END);
}
else

if (objectP->instanceList != NULL)
{
lwm2m_list_t * targetP;
for (targetP = objectP->instanceList ; targetP != NULL ; targetP = targetP->next)
Expand Down Expand Up @@ -895,14 +919,45 @@ int object_getRegisterPayload(lwm2m_context_t * contextP,
length = result;
index += length;

if (objectP->instanceList == NULL)
if (objectP->versionMajor != 0 || objectP->versionMinor != 0)
{
index--;
result = utils_stringCopy((char *)buffer + index, bufferLen - index, REG_VERSION_START);
if (result < 0) return 0;
index += result;

result = utils_uintToText(objectP->versionMajor, buffer + index, bufferLen - index);
if (result < 0) return 0;
index += result;

if( index >= bufferLen) return 0;
buffer[index++] = '.';

result = utils_uintToText(objectP->versionMinor, buffer + index, bufferLen - index);
if (result < 0) return 0;
index += result;

if( index >= bufferLen) return 0;
buffer[index++] = REG_DELIMITER;

if(objectP->instanceList != NULL)
{
start = index;
result = prv_getObjectTemplate(buffer + index, bufferLen - index, objectP->objID);
if (result < 0) return 0;
length = result;
index += length;
}
}
else if(objectP->instanceList == NULL)
{
index--;
result = utils_stringCopy((char *)buffer + index, bufferLen - index, REG_PATH_END);
if (result < 0) return 0;
index += result;
}
else

if (objectP->instanceList != NULL)
{
lwm2m_list_t * targetP;
for (targetP = objectP->instanceList ; targetP != NULL ; targetP = targetP->next)
Expand Down
160 changes: 132 additions & 28 deletions core/registration.c
Original file line number Diff line number Diff line change
Expand Up @@ -1434,61 +1434,158 @@ static int prv_parseLinkAttributes(uint8_t * data,
static int prv_getId(uint8_t * data,
uint16_t length,
uint16_t * objId,
uint16_t * instanceId)
uint16_t * instanceId,
uint8_t * versionMajor,
uint8_t * versionMinor)
{
int value;
uint16_t limit;
int result = 1;

*versionMajor = 0;
*versionMinor = 0;

// Expecting application/link-format (RFC6690)
// leading space were removed before. Remove trailing spaces.
while (length > 0 && data[length-1] == ' ') length--;

// strip open and close tags
if (length >= 1 && data[0] == REG_URI_START && data[length-1] == REG_URI_END)
{
data += 1;
length -= 2;
}
else
{
return 0;
}
// strip open tag
if (length < 1 || data[0] != REG_URI_START) return 0;
data += 1;
length -= 1;

// If there is a preceding /, remove it
if (length >= 1 && data[0] == '/')
{
data += 1;
length -= 1;
}
if (length < 1 || data[0] != '/') return 0;
data += 1;
length -= 1;

limit = 0;
while (limit < length && data[limit] != '/') limit++;
while (limit < length && data[limit] != '/' && data[limit] != REG_URI_END) limit++;
if (limit == 0 || limit >= length) return 0;
value = uri_getNumber(data, limit);
if (value < 0 || value >= LWM2M_MAX_ID) return 0;
*objId = value;

if (limit < length)
if (data[limit] == '/')
{
limit += 1;
data += limit;
length -= limit;
limit = 0;
while (limit < length && data[limit] != REG_URI_END) limit++;
if (limit >= length) return 0;

if (length > 0)
if (limit > 0)
{
value = uri_getNumber(data, length);
if (value >= 0 && value < LWM2M_MAX_ID)
value = uri_getNumber(data, limit);
if (value < 0 || value >= LWM2M_MAX_ID) return 0;
*instanceId = value;
result = 2;
}
}

// strip close tag
if (data[limit] != REG_URI_END) return 0;
limit += 1;
data += limit;
length -= limit;

if (length > 1 && data[0] == REG_ATTR_SEPARATOR)
{
data += 1;
length -= 1;

// Parse attributes
while (length > 0)
{
// Skip leading spaces
while (length > 0 && data[0] == ' ')
{
*instanceId = value;
return 2;
data += 1;
length -= 1;
}
else
if (length == 0) break;

limit = 0;
while (limit < length && data[limit] != REG_ATTR_SEPARATOR) limit++;

if (limit > 0)
{
return 0;
if (limit > ATTR_VERSION_LEN
&& memcmp(data, ATTR_VERSION_STR, ATTR_VERSION_LEN) == 0)
{
uint64_t val;
uint16_t limit2;
uint16_t extra = 0;

if(*versionMajor != 0 || *versionMinor != 0)
{
// Already seen
*versionMajor = 0;
*versionMinor = 0;
return 0;
}

if (limit < ATTR_VERSION_LEN + 2) return 0;
// Some examples use quotes, some don't. They shouldb't be
// there, but be permissive and ignore them if they are.
if (data[ATTR_VERSION_LEN] == '"')
{
data += 1;
limit -= 1;
length -= 1;
}
if(data[limit-1] == '"')
{
limit -= 1;
extra = 1;
}
if (limit < ATTR_VERSION_LEN) return 0;

limit2 = ATTR_VERSION_LEN + 1;
while (limit2 < limit && data[limit2] != '.') limit2++;

if (limit2 > limit - 2) return 0;

// Note that the LWM2M 1.1.1 spec limits the major and
// minor to 1 digit. This allow for values up to 255 in
// case it is expanded in the future or some client
// incorrectly exceeds 1 digit.
if (utils_textToUInt(data + ATTR_VERSION_LEN,
limit2 - ATTR_VERSION_LEN,
&val) == 0)
{
return 0;
}
if(val > UINT8_MAX) return 0;
*versionMajor = val;
if (utils_textToUInt(data + limit2 + 1,
limit - limit2 - 1,
&val) == 0)
{
*versionMajor = 0;
return 0;
}
if(val > UINT8_MAX)
{
*versionMajor = 0;
return 0;
}
*versionMinor = val;
limit += extra;
}
// Ignore any unrecognized attribute
}
if (data[limit] == REG_ATTR_SEPARATOR)
{
limit += 1;
}
data += limit;
length -= limit;
}
}

return 1;
return result;
}

static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload,
Expand All @@ -1513,6 +1610,8 @@ static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload,
int result;
uint16_t id;
uint16_t instance;
uint8_t versionMajor;
uint8_t versionMinor;

while (index < payloadLength && payload[index] == ' ') index++;
if (index == payloadLength) break;
Expand All @@ -1521,7 +1620,7 @@ static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload,
while (index < payloadLength && payload[index] != REG_DELIMITER) index++;
length = index - start;

result = prv_getId(payload + start, length, &id, &instance);
result = prv_getId(payload + start, length, &id, &instance, &versionMajor, &versionMinor);
if (result != 0)
{
lwm2m_client_object_t * objectP;
Expand All @@ -1535,7 +1634,12 @@ static lwm2m_client_object_t * prv_decodeRegisterPayload(uint8_t * payload,
objectP->id = id;
objList = (lwm2m_client_object_t *)LWM2M_LIST_ADD(objList, objectP);
}
if (result == 2)
if (result == 1)
{
objectP->versionMajor = versionMajor;
objectP->versionMinor = versionMinor;
}
else
{
lwm2m_list_t * instanceP;

Expand Down
5 changes: 5 additions & 0 deletions examples/client/object_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,11 @@ lwm2m_object_t * get_server_object(int serverId,
memset(serverObj, 0, sizeof(lwm2m_object_t));

serverObj->objID = 1;
#ifndef LWM2M_VERSION_1_0
// Not required, but useful for testing.
serverObj->versionMajor = 1;
serverObj->versionMinor = 1;
#endif

// Manually create an hardcoded server
serverInstance = (server_instance_t *)lwm2m_malloc(sizeof(server_instance_t));
Expand Down
3 changes: 3 additions & 0 deletions examples/client/object_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,9 @@ lwm2m_object_t * get_test_object(void)
memset(testObj, 0, sizeof(lwm2m_object_t));

testObj->objID = TEST_OBJECT_ID;
// Not required, but useful for testing.
testObj->versionMajor = 1;
testObj->versionMinor = 0;
for (i=0 ; i < 3 ; i++)
{
targetP = (prv_instance_t *)lwm2m_malloc(sizeof(prv_instance_t));
Expand Down
14 changes: 13 additions & 1 deletion examples/server/lwm2mserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,24 @@ static void prv_dump_client(lwm2m_client_t * targetP)
{
if (objectP->instanceList == NULL)
{
fprintf(stdout, "/%d, ", objectP->id);
if (objectP->versionMajor != 0 || objectP->versionMinor != 0)
{
fprintf(stdout, "/%d (%u.%u), ", objectP->id, objectP->versionMajor, objectP->versionMinor);
}
else
{
fprintf(stdout, "/%d, ", objectP->id);
}
}
else
{
lwm2m_list_t * instanceP;

if (objectP->versionMajor != 0 || objectP->versionMinor != 0)
{
fprintf(stdout, "/%d (%u.%u), ", objectP->id, objectP->versionMajor, objectP->versionMinor);
}

for (instanceP = objectP->instanceList; instanceP != NULL ; instanceP = instanceP->next)
{
fprintf(stdout, "/%d/%d, ", objectP->id, instanceP->id);
Expand Down
4 changes: 4 additions & 0 deletions include/liblwm2m.h
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,8 @@ struct _lwm2m_object_t
{
struct _lwm2m_object_t * next; // for internal use only.
uint16_t objID;
uint8_t versionMajor;
uint8_t versionMinor;
lwm2m_list_t * instanceList;
lwm2m_read_callback_t readFunc;
lwm2m_write_callback_t writeFunc;
Expand Down Expand Up @@ -648,6 +650,8 @@ typedef struct _lwm2m_client_object_
{
struct _lwm2m_client_object_ * next; // matches lwm2m_list_t::next
uint16_t id; // matches lwm2m_list_t::id
uint8_t versionMajor;
uint8_t versionMinor;
lwm2m_list_t * instanceList;
} lwm2m_client_object_t;

Expand Down