terence zhang / wakaama
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers data.c Source File

data.c

00001 /*******************************************************************************
00002 *
00003 * Copyright (c) 2013, 2014 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 *    Fabien Fleutot - Please refer to git log
00016 *    Bosch Software Innovations GmbH - Please refer to git log
00017 *
00018 *******************************************************************************/
00019 
00020 #include "internals.h"
00021 #include <float.h>
00022 
00023 // dataP array length is assumed to be 1.
00024 static int prv_textSerialize(lwm2m_data_t * dataP,
00025                              uint8_t ** bufferP)
00026 {
00027     size_t res;
00028 
00029     switch (dataP->type)
00030     {
00031     case LWM2M_TYPE_STRING:
00032         *bufferP = (uint8_t *)lwm2m_malloc(dataP->value.asBuffer.length);
00033         if (*bufferP == NULL) return 0;
00034         memcpy(*bufferP, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length);
00035         return (int)dataP->value.asBuffer.length;
00036 
00037     case LWM2M_TYPE_INTEGER:
00038         res = utils_int64ToPlainText(dataP->value.asInteger, bufferP);
00039         if (res == 0) return -1;
00040         return (int)res;
00041 
00042     case LWM2M_TYPE_FLOAT:
00043         res = utils_float64ToPlainText(dataP->value.asFloat, bufferP);
00044         if (res == 0) return -1;
00045         return (int)res;
00046 
00047     case LWM2M_TYPE_BOOLEAN:
00048         res = utils_boolToPlainText(dataP->value.asBoolean, bufferP);
00049         if (res == 0) return -1;
00050         return (int)res;
00051 
00052     case LWM2M_TYPE_OBJECT_LINK:
00053     {
00054         char stringBuffer[20];
00055         int len = snprintf(stringBuffer, 20, "%d:%d",
00056                 dataP->value.asObjLink.objectId,
00057                 dataP->value.asObjLink.objectInstanceId);
00058         *bufferP = (uint8_t *)lwm2m_malloc(len);
00059         if (*bufferP == NULL) return -1;
00060         memcpy(*bufferP, stringBuffer, len);
00061         return len;
00062     }
00063     case LWM2M_TYPE_OPAQUE:
00064     case LWM2M_TYPE_UNDEFINED:
00065     default:
00066         return -1;
00067     }
00068 }
00069 
00070 static int prv_setBuffer(lwm2m_data_t * dataP,
00071                          uint8_t * buffer,
00072                          size_t bufferLen)
00073 {
00074     dataP->value.asBuffer.buffer = (uint8_t *)lwm2m_malloc(bufferLen);
00075     if (dataP->value.asBuffer.buffer == NULL)
00076     {
00077         lwm2m_data_free(1, dataP);
00078         return 0;
00079     }
00080     dataP->value.asBuffer.length = bufferLen;
00081     memcpy(dataP->value.asBuffer.buffer, buffer, bufferLen);
00082 
00083     return 1;
00084 }
00085 
00086 lwm2m_data_t * lwm2m_data_new(int size)
00087 {
00088     lwm2m_data_t * dataP;
00089 
00090     LOG_ARG("size: %d", size);
00091     if (size <= 0) return NULL;
00092 
00093     dataP = (lwm2m_data_t *)lwm2m_malloc(size * sizeof(lwm2m_data_t));
00094 
00095     if (dataP != NULL)
00096     {
00097         memset(dataP, 0, size * sizeof(lwm2m_data_t));
00098     }
00099 
00100     return dataP;
00101 }
00102 
00103 void lwm2m_data_free(int size,
00104                      lwm2m_data_t * dataP)
00105 {
00106     int i;
00107 
00108     LOG_ARG("size: %d", size);
00109     if (size == 0 || dataP == NULL) return;
00110 
00111     for (i = 0; i < size; i++)
00112     {
00113         switch (dataP[i].type)
00114         {
00115         case LWM2M_TYPE_MULTIPLE_RESOURCE:
00116         case LWM2M_TYPE_OBJECT_INSTANCE:
00117         case LWM2M_TYPE_OBJECT:
00118             lwm2m_data_free(dataP[i].value.asChildren.count, dataP[i].value.asChildren.array);
00119             break;
00120 
00121         case LWM2M_TYPE_STRING:
00122         case LWM2M_TYPE_OPAQUE:
00123             if (dataP[i].value.asBuffer.buffer != NULL)
00124             {
00125                 lwm2m_free(dataP[i].value.asBuffer.buffer);
00126             }
00127 
00128         default:
00129             // do nothing
00130             break;
00131         }
00132     }
00133     lwm2m_free(dataP);
00134 }
00135 
00136 void lwm2m_data_encode_string(const char * string,
00137                               lwm2m_data_t * dataP)
00138 {
00139     size_t len;
00140     int res;
00141 
00142     LOG_ARG("\"%s\"", string);
00143     if (string == NULL)
00144     {
00145         len = 0;
00146     }
00147     else
00148     {
00149         for (len = 0; string[len] != 0; len++);
00150     }
00151 
00152     if (len == 0)
00153     {
00154         dataP->value.asBuffer.length = 0;
00155         dataP->value.asBuffer.buffer = NULL;
00156         res = 1;
00157     }
00158     else
00159     {
00160         res = prv_setBuffer(dataP, (uint8_t *)string, len);
00161     }
00162 
00163     if (res == 1)
00164     {
00165         dataP->type = LWM2M_TYPE_STRING;
00166     }
00167     else
00168     {
00169         dataP->type = LWM2M_TYPE_UNDEFINED;
00170     }
00171 }
00172 
00173 void lwm2m_data_encode_opaque(uint8_t * buffer,
00174                               size_t length,
00175                               lwm2m_data_t * dataP)
00176 {
00177     int res;
00178 
00179     LOG_ARG("length: %d", length);
00180     if (length == 0)
00181     {
00182         dataP->value.asBuffer.length = 0;
00183         dataP->value.asBuffer.buffer = NULL;
00184         res = 1;
00185     }
00186     else
00187     {
00188         res = prv_setBuffer(dataP, buffer, length);
00189     }
00190 
00191     if (res == 1)
00192     {
00193         dataP->type = LWM2M_TYPE_OPAQUE;
00194     }
00195     else
00196     {
00197         dataP->type = LWM2M_TYPE_UNDEFINED;
00198     }
00199 }
00200 
00201 void lwm2m_data_encode_nstring(const char * string,
00202                                size_t length,
00203                                lwm2m_data_t * dataP)
00204 {
00205     LOG_ARG("length: %d, string: \"%s\"", length, string);
00206     lwm2m_data_encode_opaque((uint8_t *)string, length, dataP);
00207 
00208     if (dataP->type == LWM2M_TYPE_OPAQUE)
00209     {
00210         dataP->type = LWM2M_TYPE_STRING;
00211     }
00212 }
00213 
00214 void lwm2m_data_encode_int(int64_t value,
00215                            lwm2m_data_t * dataP)
00216 {
00217     LOG_ARG("value: %" PRId64 "", value);
00218     dataP->type = LWM2M_TYPE_INTEGER;
00219     dataP->value.asInteger = value;
00220 }
00221 
00222 int lwm2m_data_decode_int(const lwm2m_data_t * dataP,
00223                           int64_t * valueP)
00224 {
00225     int result;
00226 
00227     LOG("Entering");
00228     switch (dataP->type)
00229     {
00230     case LWM2M_TYPE_INTEGER:
00231         *valueP = dataP->value.asInteger;
00232         result = 1;
00233         break;
00234 
00235     case LWM2M_TYPE_STRING:
00236         result = utils_plainTextToInt64(dataP->value.asBuffer.buffer, dataP->value.asBuffer.length, valueP);
00237         break;
00238 
00239     case LWM2M_TYPE_OPAQUE:
00240         result = utils_opaqueToInt(dataP->value.asBuffer.buffer, dataP->value.asBuffer.length, valueP);
00241         if (result == (int)dataP->value.asBuffer.length)
00242         {
00243             result = 1;
00244         }
00245         else
00246         {
00247             result = 0;
00248         }
00249         break;
00250 
00251     default:
00252         return 0;
00253     }
00254     LOG_ARG("result: %d, value: %" PRId64, result, *valueP);
00255 
00256     return result;
00257 }
00258 
00259 void lwm2m_data_encode_float(double value,
00260                              lwm2m_data_t * dataP)
00261 {
00262     LOG_ARG("value: %f", value);
00263     dataP->type = LWM2M_TYPE_FLOAT;
00264     dataP->value.asFloat = value;
00265 }
00266 
00267 int lwm2m_data_decode_float(const lwm2m_data_t * dataP,
00268                             double * valueP)
00269 {
00270     int result;
00271 
00272     LOG("Entering");
00273     switch (dataP->type)
00274     {
00275     case LWM2M_TYPE_FLOAT:
00276         *valueP = dataP->value.asFloat;
00277         result = 1;
00278         break;
00279 
00280     case LWM2M_TYPE_INTEGER:
00281         *valueP = (double)dataP->value.asInteger;
00282         result = 1;
00283         break;
00284 
00285     case LWM2M_TYPE_STRING:
00286         result = utils_plainTextToFloat64(dataP->value.asBuffer.buffer, dataP->value.asBuffer.length, valueP);
00287         break;
00288 
00289     case LWM2M_TYPE_OPAQUE:
00290         result = utils_opaqueToFloat(dataP->value.asBuffer.buffer, dataP->value.asBuffer.length, valueP);
00291         if (result == (int)dataP->value.asBuffer.length)
00292         {
00293             result = 1;
00294         }
00295         else
00296         {
00297             result = 0;
00298         }
00299         break;
00300 
00301     default:
00302         return 0;
00303     }
00304 
00305     LOG_ARG("result: %d, value: %f", result, *valueP);
00306 
00307     return result;
00308 }
00309 
00310 void lwm2m_data_encode_bool(bool value,
00311                             lwm2m_data_t * dataP)
00312 {
00313     LOG_ARG("value: %s", value?"true":"false");
00314     dataP->type = LWM2M_TYPE_BOOLEAN;
00315     dataP->value.asBoolean = value;
00316 }
00317 
00318 int lwm2m_data_decode_bool(const lwm2m_data_t * dataP,
00319                            bool * valueP)
00320 {
00321     int result;
00322 
00323     LOG("Entering");
00324     switch (dataP->type)
00325     {
00326     case LWM2M_TYPE_BOOLEAN:
00327         *valueP = dataP->value.asBoolean;
00328         result = 1;
00329         break;
00330 
00331     case LWM2M_TYPE_STRING:
00332         if (dataP->value.asBuffer.length != 1) return 0;
00333 
00334         switch (dataP->value.asBuffer.buffer[0])
00335         {
00336         case '0':
00337             *valueP = false;
00338             result = 1;
00339             break;
00340         case '1':
00341             *valueP = true;
00342             result = 1;
00343             break;
00344         default:
00345             result = 0;
00346             break;
00347         }
00348         break;
00349 
00350     case LWM2M_TYPE_OPAQUE:
00351         if (dataP->value.asBuffer.length != 1) return 0;
00352 
00353         switch (dataP->value.asBuffer.buffer[0])
00354         {
00355         case 0:
00356             *valueP = false;
00357             result = 1;
00358             break;
00359         case 1:
00360             *valueP = true;
00361             result = 1;
00362             break;
00363         default:
00364             result = 0;
00365             break;
00366         }
00367         break;
00368 
00369     default:
00370         result = 0;
00371         break;
00372     }
00373 
00374     LOG_ARG("result: %d, value: %s", result, *valueP ? "true" : "false");
00375 
00376     return result;
00377 }
00378 
00379 void lwm2m_data_encode_objlink(uint16_t objectId,
00380                            uint16_t objectInstanceId,
00381                            lwm2m_data_t * dataP)
00382 {
00383     LOG_ARG("value: %d/%d", objectId, objectInstanceId);
00384     dataP->type = LWM2M_TYPE_OBJECT_LINK;
00385     dataP->value.asObjLink.objectId = objectId;
00386     dataP->value.asObjLink.objectInstanceId = objectInstanceId;
00387 }
00388 
00389 void lwm2m_data_include(lwm2m_data_t * subDataP,
00390                         size_t count,
00391                         lwm2m_data_t * dataP)
00392 {
00393     LOG_ARG("count: %d", count);
00394     if (subDataP == NULL || count == 0) return;
00395 
00396     switch (subDataP[0].type)
00397     {
00398     case LWM2M_TYPE_STRING:
00399     case LWM2M_TYPE_OPAQUE:
00400     case LWM2M_TYPE_INTEGER:
00401     case LWM2M_TYPE_FLOAT:
00402     case LWM2M_TYPE_BOOLEAN:
00403     case LWM2M_TYPE_OBJECT_LINK:
00404     case LWM2M_TYPE_MULTIPLE_RESOURCE:
00405         dataP->type = LWM2M_TYPE_OBJECT_INSTANCE;
00406         break;
00407     case LWM2M_TYPE_OBJECT_INSTANCE:
00408         dataP->type = LWM2M_TYPE_OBJECT;
00409         break;
00410     default:
00411         return;
00412     }
00413     dataP->value.asChildren.count = count;
00414     dataP->value.asChildren.array = subDataP;
00415 }
00416 
00417 void lwm2m_data_encode_instances(lwm2m_data_t * subDataP,
00418                                  size_t count,
00419                                  lwm2m_data_t * dataP)
00420 {
00421     LOG_ARG("count: %d", count);
00422     lwm2m_data_include(subDataP, count, dataP);
00423     dataP->type = LWM2M_TYPE_MULTIPLE_RESOURCE;
00424 }
00425 
00426 int lwm2m_data_parse(lwm2m_uri_t * uriP,
00427                      uint8_t * buffer,
00428                      size_t bufferLen,
00429                      lwm2m_media_type_t format,
00430                      lwm2m_data_t ** dataP)
00431 {
00432     LOG_ARG("format: %s, bufferLen: %d", STR_MEDIA_TYPE(format), bufferLen);
00433     LOG_URI(uriP);
00434     switch (format)
00435     {
00436     case LWM2M_CONTENT_TEXT:
00437         if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return 0;
00438         *dataP = lwm2m_data_new(1);
00439         if (*dataP == NULL) return 0;
00440         (*dataP)->id = uriP->resourceId;
00441         (*dataP)->type = LWM2M_TYPE_STRING;
00442         return prv_setBuffer(*dataP, buffer, bufferLen);
00443 
00444     case LWM2M_CONTENT_OPAQUE:
00445         if (!LWM2M_URI_IS_SET_RESOURCE(uriP)) return 0;
00446         *dataP = lwm2m_data_new(1);
00447         if (*dataP == NULL) return 0;
00448         (*dataP)->id = uriP->resourceId;
00449         (*dataP)->type = LWM2M_TYPE_OPAQUE;
00450         return prv_setBuffer(*dataP, buffer, bufferLen);
00451 
00452 #ifdef LWM2M_OLD_CONTENT_FORMAT_SUPPORT
00453     case LWM2M_CONTENT_TLV_OLD:
00454 #endif
00455     case LWM2M_CONTENT_TLV:
00456         return tlv_parse(buffer, bufferLen, dataP);
00457 
00458 #ifdef LWM2M_SUPPORT_JSON
00459 #ifdef LWM2M_OLD_CONTENT_FORMAT_SUPPORT
00460     case LWM2M_CONTENT_JSON_OLD:
00461 #endif
00462     case LWM2M_CONTENT_JSON:
00463         return json_parse(uriP, buffer, bufferLen, dataP);
00464 #endif
00465 
00466     default:
00467         return 0;
00468     }
00469 }
00470 
00471 int lwm2m_data_serialize(lwm2m_uri_t * uriP,
00472                          int size,
00473                          lwm2m_data_t * dataP,
00474                          lwm2m_media_type_t * formatP,
00475                          uint8_t ** bufferP)
00476 {
00477     LOG_URI(uriP);
00478     LOG_ARG("size: %d, formatP: %s", size, STR_MEDIA_TYPE(*formatP));
00479 
00480     // Check format
00481     if (*formatP == LWM2M_CONTENT_TEXT
00482      || *formatP == LWM2M_CONTENT_OPAQUE)
00483     {
00484         if (size != 1
00485          || (uriP != NULL && !LWM2M_URI_IS_SET_RESOURCE(uriP))
00486          || dataP->type == LWM2M_TYPE_OBJECT
00487          || dataP->type == LWM2M_TYPE_OBJECT_INSTANCE
00488          || dataP->type == LWM2M_TYPE_MULTIPLE_RESOURCE)
00489         {
00490 #ifdef LWM2M_SUPPORT_JSON
00491             *formatP = LWM2M_CONTENT_JSON;
00492 #else
00493             *formatP = LWM2M_CONTENT_TLV;
00494 #endif
00495         }
00496     }
00497 
00498     if (*formatP == LWM2M_CONTENT_TEXT
00499      && dataP->type == LWM2M_TYPE_OPAQUE)
00500     {
00501         *formatP = LWM2M_CONTENT_OPAQUE;
00502     }
00503     LOG_ARG("Final format: %s", STR_MEDIA_TYPE(*formatP));
00504 
00505     switch (*formatP)
00506     {
00507     case LWM2M_CONTENT_TEXT:
00508         return prv_textSerialize(dataP, bufferP);
00509 
00510     case LWM2M_CONTENT_OPAQUE:
00511         *bufferP = (uint8_t *)lwm2m_malloc(dataP->value.asBuffer.length);
00512         if (*bufferP == NULL) return -1;
00513         memcpy(*bufferP, dataP->value.asBuffer.buffer, dataP->value.asBuffer.length);
00514         return (int)dataP->value.asBuffer.length;
00515 
00516     case LWM2M_CONTENT_TLV:
00517         {
00518             bool isResourceInstance;
00519 
00520             if (uriP != NULL && LWM2M_URI_IS_SET_RESOURCE(uriP)
00521              && (size != 1 || dataP->id != uriP->resourceId))
00522             {
00523                 isResourceInstance = true;
00524             }
00525             else
00526             {
00527                 isResourceInstance = false;
00528             }
00529             return tlv_serialize(isResourceInstance, size, dataP, bufferP);
00530         }
00531 
00532 #ifdef LWM2M_CLIENT_MODE
00533     case LWM2M_CONTENT_LINK:
00534         return discover_serialize(NULL, uriP, NULL, size, dataP, bufferP);
00535 #endif
00536 #ifdef LWM2M_SUPPORT_JSON
00537     case LWM2M_CONTENT_JSON:
00538         return json_serialize(uriP, size, dataP, bufferP);
00539 #endif
00540 
00541     default:
00542         return -1;
00543     }
00544 }
00545