terence zhang / wakaama-core
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers discover.c Source File

discover.c

00001 /*******************************************************************************
00002 *
00003 * Copyright (c) 2015 Intel Corporation and others.
00004 * All rights reserved. This program and the accompanying materials
00005 * are made available under the terms of the Eclipse Public License v1.0
00006 * and Eclipse Distribution License v1.0 which accompany this distribution.
00007 *
00008 * The Eclipse Public License is available at
00009 *    http://www.eclipse.org/legal/epl-v10.html
00010 * The Eclipse Distribution License is available at
00011 *    http://www.eclipse.org/org/documents/edl-v10.php.
00012 *
00013 * Contributors:
00014 *    David Navarro, Intel Corporation - initial API and implementation
00015 *
00016 *******************************************************************************/
00017 
00018 
00019 #include "internals.h"
00020 
00021 #define PRV_LINK_BUFFER_SIZE  1024
00022 
00023 
00024 #define PRV_CONCAT_STR(buf, len, index, str, str_len)    \
00025     {                                                    \
00026         if ((len)-(index) < (str_len)) return -1;        \
00027         memcpy((buf)+(index), (str), (str_len));         \
00028         (index) += (str_len);                            \
00029     }
00030 
00031 
00032 #ifdef LWM2M_CLIENT_MODE
00033 
00034 static lwm2m_attributes_t * prv_findAttributes(lwm2m_context_t * contextP,
00035                                                lwm2m_uri_t * uriP,
00036                                                lwm2m_server_t * serverP)
00037 {
00038     lwm2m_observed_t * observedP;
00039     lwm2m_watcher_t * watcherP;
00040     lwm2m_attributes_t * paramP;
00041 
00042     paramP = NULL;
00043 
00044     if (contextP == NULL) return NULL;
00045     if (serverP == NULL) return NULL;
00046 
00047     observedP = observe_findByUri(contextP, uriP);
00048     if (observedP == NULL || observedP->watcherList == NULL) return NULL;
00049 
00050     for (watcherP = observedP->watcherList; watcherP != NULL; watcherP = watcherP->next)
00051     {
00052         if (watcherP->server == serverP)
00053         {
00054             paramP = watcherP->parameters;
00055         }
00056     }
00057 
00058     return paramP;
00059 }
00060 
00061 static int prv_serializeAttributes(lwm2m_context_t * contextP,
00062                                    lwm2m_uri_t * uriP,
00063                                    lwm2m_server_t * serverP,
00064                                    lwm2m_attributes_t * objectParamP,
00065                                    uint8_t * buffer,
00066                                    size_t uriLen,
00067                                    size_t bufferLen)
00068 {
00069     int head;
00070     int res;
00071     lwm2m_attributes_t * paramP;
00072 
00073     head = 0;
00074 
00075     paramP = prv_findAttributes(contextP, uriP, serverP);
00076     if (paramP == NULL) paramP = objectParamP;
00077 
00078     if (paramP != NULL)
00079     {
00080         head = uriLen;
00081 
00082         if (paramP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
00083         {
00084             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00085             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);
00086 
00087             res = utils_intToText(paramP->minPeriod, buffer + head, bufferLen - head);
00088             if (res <= 0) return -1;
00089             head += res;
00090         }
00091         else if (objectParamP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
00092         {
00093             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00094             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MIN_PERIOD_STR, ATTR_MIN_PERIOD_LEN);
00095 
00096             res = utils_intToText(objectParamP->minPeriod, buffer + head, bufferLen - head);
00097             if (res <= 0) return -1;
00098             head += res;
00099         }
00100 
00101         if (paramP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
00102         {
00103             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00104             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);
00105 
00106             res = utils_intToText(paramP->maxPeriod, buffer + head, bufferLen - head);
00107             if (res <= 0) return -1;
00108             head += res;
00109         }
00110         else if (objectParamP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
00111         {
00112             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00113             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_MAX_PERIOD_STR, ATTR_MAX_PERIOD_LEN);
00114 
00115             res = utils_intToText(objectParamP->maxPeriod, buffer + head, bufferLen - head);
00116             if (res <= 0) return -1;
00117             head += res;
00118         }
00119 
00120         if (paramP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN)
00121         {
00122             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00123             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_GREATER_THAN_STR, ATTR_GREATER_THAN_LEN);
00124 
00125             res = utils_floatToText(paramP->greaterThan, buffer + head, bufferLen - head);
00126             if (res <= 0) return -1;
00127             head += res;
00128         }
00129         if (paramP->toSet & LWM2M_ATTR_FLAG_LESS_THAN)
00130         {
00131             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00132             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_LESS_THAN_STR, ATTR_LESS_THAN_LEN);
00133 
00134             res = utils_floatToText(paramP->lessThan, buffer + head, bufferLen - head);
00135             if (res <= 0) return -1;
00136             head += res;
00137         }
00138         if (paramP->toSet & LWM2M_ATTR_FLAG_STEP)
00139         {
00140             PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ATTR_SEPARATOR, LINK_ATTR_SEPARATOR_SIZE);
00141             PRV_CONCAT_STR(buffer, bufferLen, head, ATTR_STEP_STR, ATTR_STEP_LEN);
00142 
00143             res = utils_floatToText(paramP->step, buffer + head, bufferLen - head);
00144             if (res <= 0) return -1;
00145             head += res;
00146         }
00147         PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_ATTR_END, LINK_ITEM_ATTR_END_SIZE);
00148     }
00149 
00150     if (head > 0) head -= uriLen + 1;
00151 
00152     return head;
00153 }
00154 
00155 static int prv_serializeLinkData(lwm2m_context_t * contextP,
00156                                  lwm2m_data_t * tlvP,
00157                                  lwm2m_server_t * serverP,
00158                                  lwm2m_attributes_t * objectParamP,
00159                                  lwm2m_uri_t * parentUriP,
00160                                  uint8_t * parentUriStr,
00161                                  size_t parentUriLen,
00162                                  uint8_t * buffer,
00163                                  size_t bufferLen)
00164 {
00165     int head;
00166     int res;
00167     lwm2m_uri_t uri;
00168 
00169     head = 0;
00170 
00171     switch (tlvP->type)
00172     {
00173     case LWM2M_TYPE_UNDEFINED:
00174     case LWM2M_TYPE_STRING:
00175     case LWM2M_TYPE_OPAQUE:
00176     case LWM2M_TYPE_INTEGER:
00177     case LWM2M_TYPE_FLOAT:
00178     case LWM2M_TYPE_BOOLEAN:
00179     case LWM2M_TYPE_OBJECT_LINK:
00180     case LWM2M_TYPE_MULTIPLE_RESOURCE:
00181         if (bufferLen < LINK_ITEM_START_SIZE) return -1;
00182         memcpy(buffer + head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
00183         head = LINK_ITEM_START_SIZE;
00184 
00185         if (parentUriLen > 0)
00186         {
00187             if (bufferLen - head < parentUriLen) return -1;
00188             memcpy(buffer + head, parentUriStr, parentUriLen);
00189             head += parentUriLen;
00190         }
00191 
00192         if (bufferLen - head < LINK_URI_SEPARATOR_SIZE) return -1;
00193         memcpy(buffer + head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
00194         head += LINK_URI_SEPARATOR_SIZE;
00195 
00196         res = utils_intToText(tlvP->id, buffer + head, bufferLen - head);
00197         if (res <= 0) return -1;
00198         head += res;
00199 
00200         if (tlvP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
00201         {
00202             if (bufferLen - head < LINK_ITEM_DIM_START_SIZE) return -1;
00203             memcpy(buffer + head, LINK_ITEM_DIM_START, LINK_ITEM_DIM_START_SIZE);
00204             head += LINK_ITEM_DIM_START_SIZE;
00205 
00206             res = utils_intToText(tlvP->value.asChildren.count, buffer + head, bufferLen - head);
00207             if (res <= 0) return -1;
00208             head += res;
00209 
00210             if (bufferLen - head < LINK_ITEM_ATTR_END_SIZE) return -1;
00211             memcpy(buffer + head, LINK_ITEM_ATTR_END, LINK_ITEM_ATTR_END_SIZE);
00212             head += LINK_ITEM_ATTR_END_SIZE;
00213         }
00214         else
00215         {
00216             if (bufferLen - head < LINK_ITEM_END_SIZE) return -1;
00217             memcpy(buffer + head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
00218             head += LINK_ITEM_END_SIZE;
00219         }
00220 
00221         if (serverP != NULL)
00222         {
00223             memcpy(&uri, parentUriP, sizeof(lwm2m_uri_t));
00224             uri.resourceId = tlvP->id;
00225             uri.flag |= LWM2M_URI_FLAG_RESOURCE_ID;
00226             res = prv_serializeAttributes(contextP, &uri, serverP, objectParamP, buffer, head - 1, bufferLen);
00227             if (res < 0) return -1;    // careful, 0 is valid
00228             if (res > 0) head += res;
00229         }
00230         break;
00231 
00232     case LWM2M_TYPE_OBJECT_INSTANCE:
00233     {
00234         uint8_t uriStr[URI_MAX_STRING_LEN];
00235         size_t uriLen;
00236         size_t index;
00237 
00238         if (parentUriLen > 0)
00239         {
00240             if (URI_MAX_STRING_LEN < parentUriLen) return -1;
00241             memcpy(uriStr, parentUriStr, parentUriLen);
00242             uriLen = parentUriLen;
00243         }
00244         else
00245         {
00246             uriLen = 0;
00247         }
00248 
00249         if (URI_MAX_STRING_LEN - uriLen < LINK_URI_SEPARATOR_SIZE) return -1;
00250         memcpy(uriStr + uriLen, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
00251         uriLen += LINK_URI_SEPARATOR_SIZE;
00252 
00253         res = utils_intToText(tlvP->id, uriStr + uriLen, URI_MAX_STRING_LEN - uriLen);
00254         if (res <= 0) return -1;
00255         uriLen += res;
00256 
00257         memcpy(&uri, parentUriP, sizeof(lwm2m_uri_t));
00258         uri.instanceId = tlvP->id;
00259         uri.flag |= LWM2M_URI_FLAG_INSTANCE_ID;
00260 
00261         head = 0;
00262         PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
00263         PRV_CONCAT_STR(buffer, bufferLen, head, uriStr, uriLen);
00264         PRV_CONCAT_STR(buffer, bufferLen, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
00265         if (serverP != NULL)
00266         {
00267             res = prv_serializeAttributes(contextP, &uri, serverP, NULL, buffer, head - 1, bufferLen);
00268             if (res < 0) return -1;    // careful, 0 is valid
00269             if (res == 0) head = 0;    // rewind
00270             else head += res;
00271         }
00272         for (index = 0; index < tlvP->value.asChildren.count; index++)
00273         {
00274             res = prv_serializeLinkData(contextP, tlvP->value.asChildren.array + index, serverP, objectParamP, &uri, uriStr, uriLen, buffer + head, bufferLen - head);
00275             if (res < 0) return -1;
00276             head += res;
00277         }
00278     }
00279     break;
00280 
00281     case LWM2M_TYPE_OBJECT:
00282     default:
00283         return -1;
00284     }
00285 
00286     return head;
00287 }
00288 
00289 int discover_serialize(lwm2m_context_t * contextP,
00290                        lwm2m_uri_t * uriP,
00291                        lwm2m_server_t * serverP,
00292                        int size,
00293                        lwm2m_data_t * dataP,
00294                        uint8_t ** bufferP)
00295 {
00296     uint8_t bufferLink[PRV_LINK_BUFFER_SIZE];
00297     uint8_t baseUriStr[URI_MAX_STRING_LEN];
00298     int baseUriLen;
00299     int index;
00300     size_t head;
00301     int res;
00302     lwm2m_uri_t parentUri;
00303     lwm2m_attributes_t * paramP;
00304     lwm2m_attributes_t mergedParam;
00305 
00306     LOG_ARG("size: %d", size);
00307     LOG_URI(uriP);
00308 
00309     head = 0;
00310     memset(&parentUri, 0, sizeof(lwm2m_uri_t));
00311     parentUri.objectId = uriP->objectId;
00312     parentUri.flag = LWM2M_URI_FLAG_OBJECT_ID;
00313 
00314     if (LWM2M_URI_IS_SET_RESOURCE(uriP))
00315     {
00316         lwm2m_uri_t tempUri;
00317         lwm2m_attributes_t * objParamP;
00318         lwm2m_attributes_t * instParamP;
00319 
00320         memset(&parentUri, 0, sizeof(lwm2m_uri_t));
00321         tempUri.objectId = uriP->objectId;
00322         tempUri.flag = LWM2M_URI_FLAG_OBJECT_ID;
00323 
00324         // get object level attributes
00325         objParamP = prv_findAttributes(contextP, &tempUri, serverP);
00326         
00327         // get object instance level attributes
00328         tempUri.instanceId = uriP->instanceId;
00329         tempUri.flag = LWM2M_URI_FLAG_INSTANCE_ID;
00330         instParamP = prv_findAttributes(contextP, &tempUri, serverP);
00331 
00332         if (objParamP != NULL)
00333         {
00334             if (instParamP != NULL)
00335             {
00336                 memset(&mergedParam, 0, sizeof(lwm2m_attributes_t));
00337                 mergedParam.toSet = objParamP->toSet | instParamP->toSet;
00338                 if (mergedParam.toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
00339                 {
00340                     if (instParamP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
00341                     {
00342                         mergedParam.minPeriod = instParamP->minPeriod;
00343                     }
00344                     else
00345                     {
00346                         mergedParam.minPeriod = objParamP->minPeriod;
00347                     }
00348                 }
00349                 if (mergedParam.toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
00350                 {
00351                     if (instParamP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
00352                     {
00353                         mergedParam.maxPeriod = instParamP->maxPeriod;
00354                     }
00355                     else
00356                     {
00357                         mergedParam.maxPeriod = objParamP->maxPeriod;
00358                     }
00359                 }
00360                 paramP = &mergedParam;
00361             }
00362             else
00363             {
00364                 paramP = objParamP;
00365             }
00366         }
00367         else
00368         {
00369             paramP = instParamP;
00370         }
00371         uriP->flag &= ~LWM2M_URI_FLAG_RESOURCE_ID;
00372     }
00373     else
00374     {
00375         paramP = NULL;
00376 
00377         if (LWM2M_URI_IS_SET_INSTANCE(uriP))
00378         {
00379             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
00380             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
00381             res = utils_intToText(uriP->objectId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
00382             if (res <= 0) return -1;
00383             head += res;
00384             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
00385             res = utils_intToText(uriP->instanceId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
00386             if (res <= 0) return -1;
00387             head += res;
00388             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
00389             parentUri.instanceId = uriP->instanceId;
00390             parentUri.flag = LWM2M_URI_FLAG_INSTANCE_ID;
00391             if (serverP != NULL)
00392             {
00393                 res = prv_serializeAttributes(contextP, &parentUri, serverP, NULL, bufferLink, head - 1, PRV_LINK_BUFFER_SIZE);
00394                 if (res < 0) return -1;    // careful, 0 is valid
00395             }
00396             else
00397             {
00398                 res = 0;
00399             }
00400             head += res;
00401         }
00402         else
00403         {
00404             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_START, LINK_ITEM_START_SIZE);
00405             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_URI_SEPARATOR, LINK_URI_SEPARATOR_SIZE);
00406             res = utils_intToText(uriP->objectId, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
00407             if (res <= 0) return -1;
00408             head += res;
00409             PRV_CONCAT_STR(bufferLink, PRV_LINK_BUFFER_SIZE, head, LINK_ITEM_END, LINK_ITEM_END_SIZE);
00410 
00411             if (serverP != NULL)
00412             {
00413                 res = prv_serializeAttributes(contextP, &parentUri, serverP, NULL, bufferLink, head - 1, PRV_LINK_BUFFER_SIZE);
00414                 if (res < 0) return -1;    // careful, 0 is valid
00415                 head += res;
00416             }
00417         }
00418     }
00419 
00420     baseUriLen = uri_toString(uriP, baseUriStr, URI_MAX_STRING_LEN, NULL);
00421     if (baseUriLen < 0) return -1;
00422     baseUriLen -= 1;
00423 
00424     for (index = 0; index < size && head < PRV_LINK_BUFFER_SIZE; index++)
00425     {
00426         res = prv_serializeLinkData(contextP, dataP + index, serverP, paramP, uriP, baseUriStr, baseUriLen, bufferLink + head, PRV_LINK_BUFFER_SIZE - head);
00427         if (res < 0) return -1;
00428         head += res;
00429     }
00430 
00431     if (head > 0)
00432     {
00433         head -= 1;
00434 
00435         *bufferP = (uint8_t *)lwm2m_malloc(head);
00436         if (*bufferP == NULL) return 0;
00437         memcpy(*bufferP, bufferLink, head);
00438     }
00439 
00440     return (int)head;
00441 }
00442 #endif