442 lines
15 KiB
C
442 lines
15 KiB
C
/*******************************************************************************
|
|
*
|
|
* Copyright (c) 2015 Intel Corporation and others.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
|
*
|
|
* The Eclipse Public License is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
* The Eclipse Distribution License is available at
|
|
* http://www.eclipse.org/org/documents/edl-v10.php.
|
|
*
|
|
* Contributors:
|
|
* David Navarro, Intel Corporation - initial API and implementation
|
|
*
|
|
*******************************************************************************/
|
|
|
|
|
|
#include "internals.h"
|
|
|
|
#define PRV_LINK_BUFFER_SIZE 1024
|
|
|
|
|
|
#define PRV_CONCAT_STR(buf, len, index, str, str_len) \
|
|
{ \
|
|
if ((len)-(index) < (str_len)) return -1; \
|
|
memcpy((buf)+(index), (str), (str_len)); \
|
|
(index) += (str_len); \
|
|
}
|
|
|
|
|
|
#ifdef LWM2M_CLIENT_MODE
|
|
|
|
static lwm2m_attributes_t * prv_findAttributes(lwm2m_context_t * contextP,
|
|
lwm2m_uri_t * uriP,
|
|
lwm2m_server_t * serverP)
|
|
{
|
|
lwm2m_observed_t * observedP;
|
|
lwm2m_watcher_t * watcherP;
|
|
lwm2m_attributes_t * paramP;
|
|
|
|
paramP = NULL;
|
|
|
|
if (contextP == NULL) return NULL;
|
|
if (serverP == NULL) return NULL;
|
|
|
|
observedP = observe_findByUri(contextP, uriP);
|
|
if (observedP == NULL || observedP->watcherList == NULL) return NULL;
|
|
|
|
for (watcherP = observedP->watcherList; watcherP != NULL; watcherP = watcherP->next)
|
|
{
|
|
if (watcherP->server == serverP)
|
|
{
|
|
paramP = watcherP->parameters;
|
|
}
|
|
}
|
|
|
|
return paramP;
|
|
}
|
|
|
|
static int prv_serializeAttributes(lwm2m_context_t * contextP,
|
|
lwm2m_uri_t * uriP,
|
|
lwm2m_server_t * serverP,
|
|
lwm2m_attributes_t * objectParamP,
|
|
uint8_t * buffer,
|
|
size_t uriLen,
|
|
size_t bufferLen)
|
|
{
|
|
int head;
|
|
int res;
|
|
lwm2m_attributes_t * paramP;
|
|
|
|
head = 0;
|
|
|
|
paramP = prv_findAttributes(contextP, uriP, serverP);
|
|
if (paramP == NULL) paramP = objectParamP;
|
|
|
|
if (paramP != NULL)
|
|
{
|
|
head = uriLen;
|
|
|
|
if (paramP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);
|
|
|
|
res = utils_intToText(paramP->minPeriod, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
else if (objectParamP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);
|
|
|
|
res = utils_intToText(objectParamP->minPeriod, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
|
|
if (paramP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);
|
|
|
|
res = utils_intToText(paramP->maxPeriod, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
else if (objectParamP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);
|
|
|
|
res = utils_intToText(objectParamP->maxPeriod, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
|
|
if (paramP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN);
|
|
|
|
res = utils_floatToText(paramP->greaterThan, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
if (paramP->toSet & LWM2M_ATTR_FLAG_LESS_THAN)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN);
|
|
|
|
res = utils_floatToText(paramP->lessThan, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
if (paramP->toSet & LWM2M_ATTR_FLAG_STEP)
|
|
{
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_STEP_STR, ATTR_STEP_LEN);
|
|
|
|
res = utils_floatToText(paramP->step, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
}
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_ATTR_END, LINK_ITEM_ATTR_END_SIZE);
|
|
}
|
|
|
|
if (head > 0) head -= uriLen + 1;
|
|
|
|
return head;
|
|
}
|
|
|
|
static int prv_serializeLinkData(lwm2m_context_t * contextP,
|
|
lwm2m_data_t * tlvP,
|
|
lwm2m_server_t * serverP,
|
|
lwm2m_attributes_t * objectParamP,
|
|
lwm2m_uri_t * parentUriP,
|
|
uint8_t * parentUriStr,
|
|
size_t parentUriLen,
|
|
uint8_t * buffer,
|
|
size_t bufferLen)
|
|
{
|
|
int head;
|
|
int res;
|
|
lwm2m_uri_t uri;
|
|
|
|
head = 0;
|
|
|
|
switch (tlvP->type)
|
|
{
|
|
case LWM2M_TYPE_UNDEFINED:
|
|
case LWM2M_TYPE_STRING:
|
|
case LWM2M_TYPE_OPAQUE:
|
|
case LWM2M_TYPE_INTEGER:
|
|
case LWM2M_TYPE_FLOAT:
|
|
case LWM2M_TYPE_BOOLEAN:
|
|
case LWM2M_TYPE_OBJECT_LINK:
|
|
case LWM2M_TYPE_MULTIPLE_RESOURCE:
|
|
if (bufferLen < LINK_ITEM_START_SIZE) return -1;
|
|
memcpy(buffer + head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
|
|
head = LINK_ITEM_START_SIZE;
|
|
|
|
if (parentUriLen > 0)
|
|
{
|
|
if (bufferLen - head < parentUriLen) return -1;
|
|
memcpy(buffer + head, parentUriStr, parentUriLen);
|
|
head += parentUriLen;
|
|
}
|
|
|
|
if (bufferLen - head < LINK_URI_SEPARATOR_SIZE) return -1;
|
|
memcpy(buffer + head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
|
|
head += LINK_URI_SEPARATOR_SIZE;
|
|
|
|
res = utils_intToText(tlvP->id, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
|
|
if (tlvP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
|
|
{
|
|
if (bufferLen - head < LINK_ITEM_DIM_START_SIZE) return -1;
|
|
memcpy(buffer + head, LINK_ITEM_DIM_START, LINK_ITEM_DIM_START_SIZE);
|
|
head += LINK_ITEM_DIM_START_SIZE;
|
|
|
|
res = utils_intToText(tlvP->value.asChildren.count, buffer + head, bufferLen - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
|
|
if (bufferLen - head < LINK_ITEM_ATTR_END_SIZE) return -1;
|
|
memcpy(buffer + head, LINK_ITEM_ATTR_END, LINK_ITEM_ATTR_END_SIZE);
|
|
head += LINK_ITEM_ATTR_END_SIZE;
|
|
}
|
|
else
|
|
{
|
|
if (bufferLen - head < LINK_ITEM_END_SIZE) return -1;
|
|
memcpy(buffer + head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
|
|
head += LINK_ITEM_END_SIZE;
|
|
}
|
|
|
|
if (serverP != NULL)
|
|
{
|
|
memcpy(&uri, parentUriP, sizeof(lwm2m_uri_t));
|
|
uri.resourceId = tlvP->id;
|
|
uri.flag |= LWM2M_URI_FLAG_RESOURCE_ID;
|
|
res = prv_serializeAttributes(contextP, &uri, serverP, objectParamP, buffer, head - 1, bufferLen);
|
|
if (res < 0) return -1; // careful, 0 is valid
|
|
if (res > 0) head += res;
|
|
}
|
|
break;
|
|
|
|
case LWM2M_TYPE_OBJECT_INSTANCE:
|
|
{
|
|
uint8_t uriStr[URI_MAX_STRING_LEN];
|
|
size_t uriLen;
|
|
size_t index;
|
|
|
|
if (parentUriLen > 0)
|
|
{
|
|
if (URI_MAX_STRING_LEN < parentUriLen) return -1;
|
|
memcpy(uriStr, parentUriStr, parentUriLen);
|
|
uriLen = parentUriLen;
|
|
}
|
|
else
|
|
{
|
|
uriLen = 0;
|
|
}
|
|
|
|
if (URI_MAX_STRING_LEN - uriLen < LINK_URI_SEPARATOR_SIZE) return -1;
|
|
memcpy(uriStr + uriLen, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
|
|
uriLen += LINK_URI_SEPARATOR_SIZE;
|
|
|
|
res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen);
|
|
if (res <= 0) return -1;
|
|
uriLen += res;
|
|
|
|
memcpy(&uri, parentUriP, sizeof(lwm2m_uri_t));
|
|
uri.instanceId = tlvP->id;
|
|
uri.flag |= LWM2M_URI_FLAG_INSTANCE_ID;
|
|
|
|
head = 0;
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, uriStr, uriLen);
|
|
PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
|
|
if (serverP != NULL)
|
|
{
|
|
res = prv_serializeAttributes(contextP, &uri, serverP, NULL, buffer, head - 1, bufferLen);
|
|
if (res < 0) return -1; // careful, 0 is valid
|
|
if (res == 0) head = 0; // rewind
|
|
else head += res;
|
|
}
|
|
for (index = 0; index < tlvP->value.asChildren.count; index++)
|
|
{
|
|
res = prv_serializeLinkData(contextP, tlvP->value.asChildren.array + index, serverP, objectParamP, &uri, uriStr, uriLen, buffer + head, bufferLen - head);
|
|
if (res < 0) return -1;
|
|
head += res;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LWM2M_TYPE_OBJECT:
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
return head;
|
|
}
|
|
|
|
int discover_serialize(lwm2m_context_t * contextP,
|
|
lwm2m_uri_t * uriP,
|
|
lwm2m_server_t * serverP,
|
|
int size,
|
|
lwm2m_data_t * dataP,
|
|
uint8_t ** bufferP)
|
|
{
|
|
uint8_t bufferLink[PRV_LINK_BUFFER_SIZE];
|
|
uint8_t baseUriStr[URI_MAX_STRING_LEN];
|
|
int baseUriLen;
|
|
int index;
|
|
size_t head;
|
|
int res;
|
|
lwm2m_uri_t parentUri;
|
|
lwm2m_attributes_t * paramP;
|
|
lwm2m_attributes_t mergedParam;
|
|
|
|
LOG_ARG("size: %d", size);
|
|
LOG_URI(uriP);
|
|
|
|
head = 0;
|
|
memset(&parentUri, 0, sizeof(lwm2m_uri_t));
|
|
parentUri.objectId = uriP->objectId;
|
|
parentUri.flag = LWM2M_URI_FLAG_OBJECT_ID;
|
|
|
|
if (LWM2M_URI_IS_SET_RESOURCE(uriP))
|
|
{
|
|
lwm2m_uri_t tempUri;
|
|
lwm2m_attributes_t * objParamP;
|
|
lwm2m_attributes_t * instParamP;
|
|
|
|
memset(&parentUri, 0, sizeof(lwm2m_uri_t));
|
|
tempUri.objectId = uriP->objectId;
|
|
tempUri.flag = LWM2M_URI_FLAG_OBJECT_ID;
|
|
|
|
// get object level attributes
|
|
objParamP = prv_findAttributes(contextP, &tempUri, serverP);
|
|
|
|
// get object instance level attributes
|
|
tempUri.instanceId = uriP->instanceId;
|
|
tempUri.flag = LWM2M_URI_FLAG_INSTANCE_ID;
|
|
instParamP = prv_findAttributes(contextP, &tempUri, serverP);
|
|
|
|
if (objParamP != NULL)
|
|
{
|
|
if (instParamP != NULL)
|
|
{
|
|
memset(&mergedParam, 0, sizeof(lwm2m_attributes_t));
|
|
mergedParam.toSet = objParamP->toSet | instParamP->toSet;
|
|
if (mergedParam.toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
|
|
{
|
|
if (instParamP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
|
|
{
|
|
mergedParam.minPeriod = instParamP->minPeriod;
|
|
}
|
|
else
|
|
{
|
|
mergedParam.minPeriod = objParamP->minPeriod;
|
|
}
|
|
}
|
|
if (mergedParam.toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
|
|
{
|
|
if (instParamP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
|
|
{
|
|
mergedParam.maxPeriod = instParamP->maxPeriod;
|
|
}
|
|
else
|
|
{
|
|
mergedParam.maxPeriod = objParamP->maxPeriod;
|
|
}
|
|
}
|
|
paramP = &mergedParam;
|
|
}
|
|
else
|
|
{
|
|
paramP = objParamP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
paramP = instParamP;
|
|
}
|
|
uriP->flag &= ~LWM2M_URI_FLAG_RESOURCE_ID;
|
|
}
|
|
else
|
|
{
|
|
paramP = NULL;
|
|
|
|
if (LWM2M_URI_IS_SET_INSTANCE(uriP))
|
|
{
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
|
|
res = utils_intToText(uriP->objectId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
|
|
res = utils_intToText(uriP->instanceId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
|
|
parentUri.instanceId = uriP->instanceId;
|
|
parentUri.flag = LWM2M_URI_FLAG_INSTANCE_ID;
|
|
if (serverP != NULL)
|
|
{
|
|
res = prv_serializeAttributes(contextP, &parentUri, serverP, NULL, bufferLink, head - 1, PRV_LINK_BUFFER_SIZE);
|
|
if (res < 0) return -1; // careful, 0 is valid
|
|
}
|
|
else
|
|
{
|
|
res = 0;
|
|
}
|
|
head += res;
|
|
}
|
|
else
|
|
{
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
|
|
res = utils_intToText(uriP->objectId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
|
|
if (res <= 0) return -1;
|
|
head += res;
|
|
PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
|
|
|
|
if (serverP != NULL)
|
|
{
|
|
res = prv_serializeAttributes(contextP, &parentUri, serverP, NULL, bufferLink, head - 1, PRV_LINK_BUFFER_SIZE);
|
|
if (res < 0) return -1; // careful, 0 is valid
|
|
head += res;
|
|
}
|
|
}
|
|
}
|
|
|
|
baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, NULL);
|
|
if (baseUriLen < 0) return -1;
|
|
baseUriLen -= 1;
|
|
|
|
for (index = 0; index < size && head < PRV_LINK_BUFFER_SIZE; index++)
|
|
{
|
|
res = prv_serializeLinkData(contextP, dataP + index, serverP, paramP, uriP, baseUriStr, baseUriLen, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
|
|
if (res < 0) return -1;
|
|
head += res;
|
|
}
|
|
|
|
if (head > 0)
|
|
{
|
|
head -= 1;
|
|
|
|
*bufferP = (uint8_t *)lwm2m_malloc(head);
|
|
if (*bufferP == NULL) return 0;
|
|
memcpy(*bufferP, bufferLink, head);
|
|
}
|
|
|
|
return (int)head;
|
|
}
|
|
#endif |