Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

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 if (resource->resource_instance_type() == M2MResourceBase::FLOAT) {
00138             success = serialize_TLV_binary_float(resource, TYPE_RESOURCE, resource->name_id(), data, size);
00139         }
00140         else {
00141              success = serialize_TILV(TYPE_RESOURCE, resource->name_id(),
00142                       resource->value(), resource->value_length(), data, size);
00143         }
00144     }
00145     return success;
00146 }
00147 
00148 bool M2MTLVSerializer::serialize_multiple_resource(const M2MResource *resource, uint8_t *&data, uint32_t &size)
00149 {
00150     bool success = false;
00151     uint8_t *nested_data = NULL;
00152     uint32_t nested_data_size = 0;
00153 
00154     const M2MResourceInstanceList &instance_list = resource->resource_instances();
00155     if(!instance_list.empty()) {
00156         M2MResourceInstanceList::const_iterator it;
00157         it = instance_list.begin();
00158         for (; it!=instance_list.end(); it++) {
00159             uint16_t id = (*it)->instance_id();
00160             if (((*it)->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
00161                 if(!serialize_resource_instance(id, (*it), nested_data, nested_data_size)) {
00162                     /* serializing instance has failed */
00163                     /* free data so far allocated */
00164                     free(nested_data);
00165                     /* return fail immediately*/
00166                     success = false;
00167                     return success;
00168                 }
00169             }
00170         }
00171     }
00172     if(resource->name_id() != -1 &&
00173             (resource->operation() & M2MBase::GET_ALLOWED) == M2MBase::GET_ALLOWED) {
00174         success = serialize_TILV(TYPE_MULTIPLE_RESOURCE, resource->name_id(),
00175                                     nested_data, nested_data_size, data, size);
00176     }
00177 
00178     free(nested_data);
00179     return success;
00180 }
00181 
00182 bool M2MTLVSerializer::serialize_resource_instance(uint16_t id, const M2MResourceInstance *resource, uint8_t *&data, uint32_t &size)
00183 {
00184     bool success;
00185 
00186     if ( (resource->resource_instance_type() == M2MResourceBase::INTEGER) ||
00187          (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) ||
00188          (resource->resource_instance_type() == M2MResourceBase::TIME) ) {
00189         success=serialize_TLV_binary_int(resource, TYPE_RESOURCE_INSTANCE, id, data, size);
00190     }
00191     else if (resource->resource_instance_type() == M2MResourceBase::FLOAT) {
00192         success=serialize_TLV_binary_float(resource, TYPE_RESOURCE_INSTANCE, id, data, size);
00193     }
00194     else {
00195         success=serialize_TILV(TYPE_RESOURCE_INSTANCE, id, resource->value(), resource->value_length(), data, size);
00196     }
00197 
00198     return success;
00199 }
00200 
00201 /* See, OMA-TS-LightweightM2M-V1_0-20170208-A, Appendix C,
00202  * Data Types, Integer, Boolean and Time TLV Format */
00203 bool M2MTLVSerializer::serialize_TLV_binary_int(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size)
00204 {
00205     int64_t valueInt = resource->get_value_int();
00206     uint32_t buffer_size;
00207     /* max len 8 bytes */
00208     uint8_t buffer[8];
00209 
00210     if (resource->resource_instance_type() == M2MResourceBase::BOOLEAN) {
00211         buffer_size = 1;
00212         buffer[0] = valueInt;
00213     } else {
00214         buffer_size = 8;
00215         common_write_64_bit(valueInt, buffer);
00216     }
00217 
00218     return serialize_TILV(type, id, buffer, buffer_size, data, size);
00219 }
00220 
00221 /* See, OMA-TS-LightweightM2M-V1_0-20170208-A, Appendix C,
00222  * Data Type Float (32 bit only) TLV Format */
00223 bool M2MTLVSerializer::serialize_TLV_binary_float(const M2MResourceBase *resource, uint8_t type, uint16_t id, uint8_t *&data, uint32_t &size)
00224 {
00225     float valueFloat = resource->get_value_float();
00226     /* max len 8 bytes */
00227     uint8_t buffer[4];
00228 
00229     common_write_32_bit(*(uint32_t*)&valueFloat, buffer);
00230 
00231     return serialize_TILV(type, id, buffer, 4, data, size);
00232 }
00233 
00234 
00235 bool M2MTLVSerializer::serialize_TILV(uint8_t type, uint16_t id, uint8_t *value, uint32_t value_length, uint8_t *&data, uint32_t &size)
00236 {
00237     uint8_t *tlv = 0;
00238     const uint32_t type_length = TLV_TYPE_SIZE;
00239     type += id < 256 ? 0 : ID16;
00240     type += value_length < 8 ? value_length :
00241             value_length < 256 ? LENGTH8 :
00242             value_length < 65536 ? LENGTH16 : LENGTH24;
00243     uint8_t tlv_type;
00244     tlv_type = type & 0xFF;
00245 
00246     uint32_t id_size;
00247     uint8_t id_array[MAX_TLV_ID_SIZE];
00248     serialize_id(id, id_size, id_array);
00249 
00250     uint32_t length_size;
00251     uint8_t length_array[MAX_TLV_LENGTH_SIZE];
00252     serialize_length(value_length, length_size, length_array);
00253 
00254     tlv = (uint8_t*)malloc(size + type_length + id_size + length_size + value_length);
00255     if (!tlv) {
00256         /* memory allocation has failed */
00257         /* return failure immediately */
00258         return false;
00259         /* eventually NULL will be returned to serializer public method caller */
00260     }
00261     if(data) {
00262         memcpy(tlv, data, size);
00263         free(data);
00264     }
00265     memcpy(tlv+size, &tlv_type, type_length);
00266     memcpy(tlv+size+type_length, id_array, id_size);
00267     memcpy(tlv+size+type_length+id_size, length_array, length_size);
00268     memcpy(tlv+size+type_length+id_size+length_size, value, value_length);
00269 
00270     data = tlv;
00271     size += type_length + id_size + length_size + value_length;
00272     return true;
00273 }
00274 
00275 void M2MTLVSerializer::serialize_id(uint16_t id, uint32_t &size, uint8_t *id_ptr)
00276 {
00277     if(id > 255) {
00278         size=2;
00279         id_ptr[0] = (id & 0xFF00) >> 8;
00280         id_ptr[1] = id & 0xFF;
00281     } else {
00282         size=1;
00283         id_ptr[0] = id & 0xFF;
00284     }
00285 }
00286 
00287 void M2MTLVSerializer::serialize_length(uint32_t length, uint32_t &size, uint8_t *length_ptr)
00288 {
00289     if (length > 65535) {
00290         size = 3;
00291         length_ptr[0] = (length & 0xFF0000) >> 16;
00292         length_ptr[1] = (length & 0xFF00) >> 8;
00293         length_ptr[2] = length & 0xFF;
00294     } else if (length > 255) {
00295         size = 2;
00296         length_ptr[0] = (length & 0xFF00) >> 8;
00297         length_ptr[1] = length & 0xFF;
00298     } else if (length > 7) {
00299         size = 1;
00300         length_ptr[0] = length & 0xFF;
00301     } else {
00302         size=0;
00303     }
00304 }
00305