Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
wakaama/discover.c
- Committer:
- terencez
- Date:
- 2017-05-06
- Revision:
- 14:ec9e195830ff
File content as of revision 14:ec9e195830ff:
/*******************************************************************************
*
* 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