Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mtlvserializer.cpp Source File

m2mtlvserializer.cpp

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "include/m2mtlvserializer.h"
00017 #include "mbed-client/m2mconstants.h"
00018 
00019 #include <stdlib.h>
00020 #include "common_functions.h"
00021 
00022 #define TRACE_GROUP "mClt"
00023 
00024 #define MAX_TLV_LENGTH_SIZE 3
00025 #define MAX_TLV_ID_SIZE 2
00026 #define TLV_TYPE_SIZE 1
00027 
00028 uint8_t* M2MTLVSerializer::serialize(const M2MObjectInstanceList &object_instance_list, uint32_t &size)
00029 {
00030     return serialize_object_instances(object_instance_list, size);
00031 }
00032 
00033 uint8_t* M2MTLVSerializer::serialize(const M2MResourceList &resource_list, uint32_t &size)
00034 {
00035     bool valid = true;
00036     return serialize_resources(resource_list, size,valid);
00037 }
00038 
00039 uint8_t* M2MTLVSerializer::serialize(const M2MResource *resource, uint32_t &size)
00040 {
00041     uint8_t* data = NULL;
00042     serialize(resource, data, size);
00043     return data;
00044 }
00045 
00046 uint8_t* M2MTLVSerializer::serialize_object_instances(const M2MObjectInstanceList &object_instance_list, uint32_t &size)
00047 {
00048     uint8_t *data = NULL;
00049 
00050     if(!object_instance_list.empty()) {
00051         M2MObjectInstanceList::const_iterator it;
00052         it = object_instance_list.begin();
00053         for (; it!=object_instance_list.end(); it++) {            
00054             uint16_t id = (*it)->instance_id();
00055             serialize(id, *it, data, size);            
00056         }
00057     }
00058     return data;
00059 }
00060 
00061 uint8_t* M2MTLVSerializer::serialize_resources(const M2MResourceList &resource_list, uint32_t &size, bool &valid)
00062 {
00063     uint8_t *data = NULL;
00064 
00065     if(!resource_list.empty()) {
00066         M2MResourceList::const_iterator it;
00067         it = resource_list.begin();
00068         for (; it!=resource_list.end(); it++) {
00069             if((*it)->name_id() == -1) {
00070                 valid = false;
00071                 break;
00072             }
00073         }
00074         if(valid) {
00075             it = resource_list.begin();
00076             for (; it!=resource_list.end(); it++) {
00077                 if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
00078                     if(!serialize(*it, data, size)) {
00079                         /* serializing has failed */
00080                         /* free data so far */
00081                         free(data);
00082                         /* invalidate */
00083                         valid = false;
00084                         /* return NULL immediately */
00085                         return NULL;
00086                     }
00087                 }
00088             }
00089         }
00090     }
00091     return data;
00092 }
00093 
00094 bool M2MTLVSerializer::serialize(uint16_t id, const M2MObjectInstance *object_instance, uint8_t *&data, uint32_t &size)
00095 {
00096     uint8_t *resource_data = NULL;
00097     uint32_t resource_size = 0;
00098     bool success;
00099 
00100     bool valid = true;
00101     resource_data = serialize_resources(object_instance->resources(),resource_size,valid);
00102     if(valid) {
00103         if(serialize_TILV(TYPE_OBJECT_INSTANCE, id, resource_data, resource_size, data, size)) {
00104             success = true;
00105         } else {
00106             /* serializing object instance failed */
00107             success = false;
00108         }
00109         free(resource_data);
00110     } else {
00111         /* serializing resources failed */
00112         success = false;
00113     }
00114     return success;
00115 }
00116 
00117 bool M2MTLVSerializer::serialize(const M2MResource *resource, uint8_t *&data, uint32_t &size)
00118 {
00119     bool success = false;
00120     if(resource->name_id() != -1) {
00121         success = resource->supports_multiple_instances() ?
00122                 serialize_multiple_resource(resource, data, size) :
00123                 serialize_resource(resource, data, size);
00124     }
00125     return success;
00126 }
00127 
00128 bool M2MTLVSerializer::serialize_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size)
00129 {
00130     bool success = false;
00131     if(resource->name_id() != -1) {
00132         if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) ||
00133              (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) ||
00134              (resource->resource_instance_type() == M2MResourceBase::TIME) ) {
00135             success = serialize_TLV_binary_int(resource, TYPE_RESOURCE, resource->name_id(), data, size);
00136         }
00137         else {
00138              success = serialize_TILV(TYPE_RESOURCE, resource->name_id(),
00139                       resource->value(), resource->value_length(), data, size);
00140         }
00141     }
00142     return success;
00143 }
00144 
00145 bool M2MTLVSerializer::serialize_multiple_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size)
00146 {
00147     bool success = false;
00148     uint8_t *nested_data = NULL;
00149     uint32_t nested_data_size = 0;
00150 
00151     const M2MResourceInstanceList &instance_list = resource->resource_instances();
00152     if(!instance_list.empty()) {
00153         M2MResourceInstanceList::const_iterator it;
00154         it = instance_list.begin();
00155         for (; it!=instance_list.end(); it++) {
00156             uint16_t id = (*it)->instance_id();
00157             if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
00158                 if(!serialize_resource_instance(id, (*it), nested_data, nested_data_size)) {
00159                     /* serializing instance has failed */
00160                     /* free data so far allocated */
00161                     free(nested_data);
00162                     /* return fail immediately*/
00163                     success = false;
00164                     return success;
00165                 }
00166             }
00167         }
00168     }
00169     if(resource->name_id() != -1 &&
00170             (resource->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
00171         success = serialize_TILV(TYPE_MULTIPLE_RESOURCE, resource->name_id(),
00172                                     nested_data, nested_data_size, data, size);
00173     }
00174 
00175     free(nested_data);
00176     return success;
00177 }
00178 
00179 bool M2MTLVSerializer::serialize_resource_instance(uint16_t id, const M2MResourceInstance *resource, uint8_t *&data, uint32_t &size)
00180 {
00181     bool success;
00182 
00183     if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) ||
00184          (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) ||
00185          (resource->resource_instance_type() == M2MResourceBase::TIME) ) {
00186         success=serialize_TLV_binary_int(resource, TYPE_RESOURCE_INSTANCE, id, data, size);
00187         }
00188     else {
00189         success=serialize_TILV(TYPE_RESOURCE_INSTANCE, id, resource->value(), resource->value_length(), data, size);
00190     }
00191 
00192     return success;
00193 }
00194 
00195 /* See, OMA-TS-LightweightM2M-V1_0-20170208-A, Appendix C,
00196  * Data Types, Integer, Boolean and TY
00197  * Yime, TLV Format */
00198 bool M2MTLVSerializer::serialize_TLV_binary_int(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size)
00199 {
00200     int64_t valueInt = resource->get_value_int();
00201     uint32_t buffer_size;
00202     /* max len 8 bytes */
00203     uint8_t buffer[8];
00204 
00205     if (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) {
00206         buffer_size = 1;
00207         buffer[0] = valueInt;
00208     } else {
00209         buffer_size = 8;
00210         common_write_64_bit(valueInt, buffer);
00211     }
00212 
00213     return serialize_TILV(type, id, buffer, buffer_size, data, size);
00214 }
00215 
00216 
00217 bool M2MTLVSerializer::serialize_TILV(uint8_t type, uint16_t id, uint8_t *value, uint32_t value_length, uint8_t *&data, uint32_t &size)
00218 {
00219     uint8_t *tlv = 0;
00220     const uint32_t type_length = TLV_TYPE_SIZE;
00221     type += id < 256 ? 0 : ID16;
00222     type += value_length < 8 ? value_length :
00223             value_length < 256 ? LENGTH8 :
00224             value_length < 65536 ? LENGTH16 : LENGTH24;
00225     uint8_t tlv_type;
00226     tlv_type = type & 0xFF;
00227 
00228     uint32_t id_size;
00229     uint8_t id_array[MAX_TLV_ID_SIZE];
00230     serialize_id(id, id_size, id_array);
00231 
00232     uint32_t length_size;
00233     uint8_t length_array[MAX_TLV_LENGTH_SIZE];
00234     serialize_length(value_length, length_size, length_array);
00235 
00236     tlv = (uint8_t*)malloc(size + type_length + id_size + length_size + value_length);
00237     if (!tlv) {
00238         /* memory allocation has failed */
00239         /* return failure immediately */
00240         return false;
00241         /* eventually NULL will be returned to serializer public method caller */
00242     }
00243     if(data) {
00244         memcpy(tlv, data, size);
00245         free(data);
00246     }
00247     memcpy(tlv+size, &tlv_type, type_length);
00248     memcpy(tlv+size+type_length, id_array, id_size);
00249     memcpy(tlv+size+type_length+id_size, length_array, length_size);
00250     memcpy(tlv+size+type_length+id_size+length_size, value, value_length);
00251 
00252     data = tlv;
00253     size += type_length + id_size + length_size + value_length;
00254     return true;
00255 }
00256 
00257 void M2MTLVSerializer::serialize_id(uint16_t id, uint32_t &size, uint8_t *id_ptr)
00258 {
00259     if(id > 255) {
00260         size=2;
00261         id_ptr[0] = (id & 0xFF00) >> 8;
00262         id_ptr[1] = id & 0xFF;
00263     } else {
00264         size=1;
00265         id_ptr[0] = id & 0xFF;
00266     }
00267 }
00268 
00269 void M2MTLVSerializer::serialize_length(uint32_t length, uint32_t &size, uint8_t *length_ptr)
00270 {
00271     if (length > 65535) {
00272         size = 3;
00273         length_ptr[0] = (length & 0xFF0000) >> 16;
00274         length_ptr[1] = (length & 0xFF00) >> 8;
00275         length_ptr[2] = length & 0xFF;
00276     } else if (length > 255) {
00277         size = 2;
00278         length_ptr[0] = (length & 0xFF00) >> 8;
00279         length_ptr[1] = length & 0xFF;
00280     } else if (length > 7) {
00281         size = 1;
00282         length_ptr[0] = length & 0xFF;
00283     } else {
00284         size=0;
00285     }
00286 }
00287