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.
m2mtlvdeserializer.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 // Needed for PRIu64 on FreeRTOS 00017 #include <stdio.h> 00018 // Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX 00019 #ifndef __STDC_LIMIT_MACROS 00020 #define __STDC_LIMIT_MACROS 00021 #endif 00022 00023 // Note: this macro is needed on armcc to get the the PRI*32 macros 00024 // from inttypes.h in a C++ code. 00025 #ifndef __STDC_FORMAT_MACROS 00026 #define __STDC_FORMAT_MACROS 00027 #endif 00028 00029 #include "include/m2mtlvdeserializer.h" 00030 #include "mbed-client/m2mconstants.h" 00031 #include "mbed-trace/mbed_trace.h" 00032 #include "common_functions.h" 00033 00034 #define TRACE_GROUP "mClt" 00035 #define BUFFER_SIZE 10 00036 00037 bool M2MTLVDeserializer::is_object_instance(const uint8_t *tlv) 00038 { 00039 return is_object_instance(tlv, 0); 00040 } 00041 00042 bool M2MTLVDeserializer::is_resource(const uint8_t *tlv) 00043 { 00044 return is_resource(tlv, 0); 00045 } 00046 00047 bool M2MTLVDeserializer::is_multiple_resource(const uint8_t *tlv) 00048 { 00049 return is_multiple_resource(tlv, 0); 00050 } 00051 00052 bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv) 00053 { 00054 return is_resource_instance(tlv, 0); 00055 } 00056 00057 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialise_object_instances(const uint8_t* tlv, 00058 uint32_t tlv_size, 00059 M2MObject &object, 00060 M2MTLVDeserializer::Operation operation) 00061 { 00062 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00063 if (is_object_instance(tlv) ) { 00064 tr_debug("M2MTLVDeserializer::deserialise_object_instances"); 00065 error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,false); 00066 if(M2MTLVDeserializer::None == error) { 00067 error = deserialize_object_instances(tlv, tlv_size, 0, object,operation,true); 00068 } 00069 } else { 00070 tr_debug("M2MTLVDeserializer::deserialise_object_instances ::NotValid"); 00071 error = M2MTLVDeserializer::NotValid; 00072 } 00073 return error; 00074 } 00075 00076 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_t *tlv, 00077 uint32_t tlv_size, 00078 M2MObjectInstance &object_instance, 00079 M2MTLVDeserializer::Operation operation) 00080 { 00081 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00082 if (!is_resource(tlv) && !is_multiple_resource(tlv)) { 00083 error = M2MTLVDeserializer::NotValid; 00084 } else { 00085 error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,false); 00086 if(M2MTLVDeserializer::None == error) { 00087 if (M2MTLVDeserializer::Put == operation) { 00088 remove_resources(tlv, tlv_size, object_instance, 0); 00089 } 00090 error = deserialize_resources(tlv, tlv_size, 0, object_instance, operation,true); 00091 } 00092 } 00093 return error; 00094 } 00095 00096 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, 00097 uint32_t tlv_size, 00098 M2MResource &resource, 00099 M2MTLVDeserializer::Operation operation) 00100 { 00101 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00102 if (!is_multiple_resource(tlv)) { 00103 error = M2MTLVDeserializer::NotValid; 00104 } else { 00105 tr_debug("M2MTLVDeserializer::deserialize_resource_instances()"); 00106 uint8_t offset = 2; 00107 00108 ((tlv[0] & 0x20) == 0) ? offset : offset++; 00109 00110 uint8_t length = tlv[0] & 0x18; 00111 if(length == 0x08) { 00112 offset += 1; 00113 } else if(length == 0x10) { 00114 offset += 2; 00115 } else if(length == 0x18) { 00116 offset += 3; 00117 } 00118 00119 tr_debug("M2MTLVDeserializer::deserialize_resource_instances() Offset %d", offset); 00120 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,false); 00121 if(M2MTLVDeserializer::None == error) { 00122 if (M2MTLVDeserializer::Put == operation) { 00123 remove_resource_instances(tlv, tlv_size, resource, offset); 00124 } 00125 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation,true); 00126 } 00127 } 00128 return error; 00129 } 00130 00131 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_object_instances(const uint8_t *tlv, 00132 uint32_t tlv_size, 00133 uint32_t offset, 00134 M2MObject &object, 00135 M2MTLVDeserializer::Operation operation, 00136 bool update_value) 00137 { 00138 tr_debug("M2MTLVDeserializer::deserialize_object_instances()"); 00139 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00140 TypeIdLength til(tlv, offset); 00141 til.deserialize(); 00142 offset = til._offset; 00143 00144 const M2MObjectInstanceList &list = object.instances(); 00145 M2MObjectInstanceList::const_iterator it; 00146 it = list.begin(); 00147 00148 if (TYPE_OBJECT_INSTANCE == til._type) { 00149 for (; it!=list.end(); it++) { 00150 if((*it)->instance_id() == til._id) { 00151 error = deserialize_resources(tlv, tlv_size, offset, (**it),operation, update_value); 00152 } 00153 } 00154 offset += til._length; 00155 00156 if(offset < tlv_size) { 00157 error = deserialize_object_instances(tlv, tlv_size, offset, object, operation, update_value); 00158 } 00159 } 00160 return error; 00161 } 00162 00163 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resources(const uint8_t *tlv, 00164 uint32_t tlv_size, 00165 uint32_t offset, 00166 M2MObjectInstance &object_instance, 00167 M2MTLVDeserializer::Operation operation, 00168 bool update_value) 00169 { 00170 tr_debug("M2MTLVDeserializer::deserialize_resources()"); 00171 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00172 TypeIdLength til(tlv, offset); 00173 til.deserialize(); 00174 offset = til._offset; 00175 00176 const M2MResourceList &list = object_instance.resources(); 00177 M2MResourceList::const_iterator it; 00178 it = list.begin(); 00179 00180 bool found = false; 00181 bool multi = false; 00182 if (TYPE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) { 00183 multi = false; 00184 for (; it!=list.end(); it++) { 00185 if((*it)->name_id() == til._id){ 00186 tr_debug("M2MTLVDeserializer::deserialize_resources() - Resource ID %d ", til._id); 00187 found = true; 00188 if(update_value) { 00189 if(til._length > 0) { 00190 tr_debug("M2MTLVDeserializer::deserialize_resources() - Update value"); 00191 if (!set_resource_instance_value((*it), tlv+offset, til._length)) { 00192 error = M2MTLVDeserializer::OutOfMemory; 00193 break; 00194 } 00195 } else { 00196 tr_debug("M2MTLVDeserializer::deserialize_resources() - Clear Value"); 00197 (*it)->clear_value(); 00198 } 00199 break; 00200 } else if(0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { 00201 tr_debug("M2MTLVDeserializer::deserialize_resources() - NOT_ALLOWED"); 00202 error = M2MTLVDeserializer::NotAllowed; 00203 break; 00204 } 00205 } 00206 } 00207 } else if (TYPE_MULTIPLE_RESOURCE == til._type) { 00208 multi = true; 00209 for (; it!=list.end(); it++) { 00210 if((*it)->supports_multiple_instances() && 00211 (*it)->name_id() == til._id) { 00212 found = true; 00213 error = deserialize_resource_instances(tlv, tlv_size, offset, (**it), object_instance, operation, update_value); 00214 } 00215 } 00216 } else { 00217 error = M2MTLVDeserializer::NotValid; 00218 return error; 00219 } 00220 00221 if (!found) { 00222 if (M2MTLVDeserializer::Post == operation) { 00223 //Create a new Resource 00224 String id; 00225 id.append_int(til._id); 00226 M2MResource *resource = object_instance.create_dynamic_resource(id, "", M2MResourceInstance::OPAQUE, true, multi); 00227 if (resource) { 00228 resource->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); 00229 if (TYPE_MULTIPLE_RESOURCE == til._type) { 00230 error = deserialize_resource_instances(tlv, tlv_size, offset, (*resource), object_instance, operation, update_value); 00231 } 00232 } 00233 } else if (M2MTLVDeserializer::Put == operation) { 00234 error = M2MTLVDeserializer::NotFound; 00235 } 00236 } 00237 00238 offset += til._length; 00239 00240 if (offset < tlv_size) { 00241 error = deserialize_resources(tlv, tlv_size, offset, object_instance, operation, update_value); 00242 } 00243 00244 return error; 00245 } 00246 00247 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, 00248 uint32_t tlv_size, 00249 uint32_t offset, 00250 M2MResource &resource, 00251 M2MObjectInstance &object_instance, 00252 M2MTLVDeserializer::Operation operation, 00253 bool update_value) 00254 { 00255 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00256 TypeIdLength til(tlv, offset); 00257 til.deserialize(); 00258 offset = til._offset; 00259 00260 if (TYPE_MULTIPLE_RESOURCE == til._type || TYPE_RESOURCE_INSTANCE == til._type) { 00261 const M2MResourceInstanceList &list = resource.resource_instances(); 00262 M2MResourceInstanceList::const_iterator it; 00263 it = list.begin(); 00264 bool found = false; 00265 for (; it!=list.end(); it++) { 00266 if((*it)->instance_id() == til._id && TYPE_RESOURCE_INSTANCE == til._type) { 00267 found = true; 00268 if(update_value) { 00269 if(til._length > 0) { 00270 if (!set_resource_instance_value((*it), tlv+offset, til._length)) { 00271 error = M2MTLVDeserializer::OutOfMemory; 00272 break; 00273 } 00274 } else { 00275 (*it)->clear_value(); 00276 } 00277 break; 00278 } else if(0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { 00279 error = M2MTLVDeserializer::NotAllowed; 00280 break; 00281 } 00282 } 00283 } 00284 00285 if(!found) { 00286 if(M2MTLVDeserializer::Post == operation) { 00287 // Create a new Resource Instance 00288 M2MResourceInstance *res_instance = object_instance.create_dynamic_resource_instance(resource.name(),"", 00289 resource.resource_instance_type(), 00290 true, 00291 til._id); 00292 if(res_instance) { 00293 res_instance->set_operation(M2MBase::GET_PUT_POST_DELETE_ALLOWED); 00294 } 00295 } else if(M2MTLVDeserializer::Put == operation) { 00296 error = M2MTLVDeserializer::NotFound; 00297 } 00298 } 00299 } else { 00300 error = M2MTLVDeserializer::NotValid; 00301 return error; 00302 } 00303 00304 offset += til._length; 00305 00306 if(offset < tlv_size) { 00307 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, object_instance, operation, update_value); 00308 } 00309 return error; 00310 } 00311 00312 M2MTLVDeserializer::Error M2MTLVDeserializer::deserialize_resource_instances(const uint8_t *tlv, 00313 uint32_t tlv_size, 00314 uint32_t offset, 00315 M2MResource &resource, 00316 M2MTLVDeserializer::Operation operation, 00317 bool update_value) 00318 { 00319 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None; 00320 TypeIdLength til(tlv, offset); 00321 til.deserialize(); 00322 offset = til._offset; 00323 00324 if (TYPE_RESOURCE_INSTANCE == til._type) { 00325 const M2MResourceInstanceList &list = resource.resource_instances(); 00326 M2MResourceInstanceList::const_iterator it; 00327 it = list.begin(); 00328 bool found = false; 00329 for (; it!=list.end(); it++) { 00330 if((*it)->instance_id() == til._id) { 00331 found = true; 00332 if(update_value) { 00333 if(til._length > 0) { 00334 if (!set_resource_instance_value((*it),tlv+offset, til._length)) { 00335 error = M2MTLVDeserializer::OutOfMemory; 00336 break; 00337 } 00338 } else { 00339 (*it)->clear_value(); 00340 } 00341 break; 00342 } else if(0 == ((*it)->operation() & M2MBase::PUT_ALLOWED)) { 00343 error = M2MTLVDeserializer::NotAllowed; 00344 break; 00345 } 00346 } 00347 } 00348 if(!found) { 00349 if(M2MTLVDeserializer::Post == operation) { 00350 error = M2MTLVDeserializer::NotAllowed; 00351 } else if(M2MTLVDeserializer::Put == operation) { 00352 error = M2MTLVDeserializer::NotFound; 00353 } 00354 } 00355 } else { 00356 error = M2MTLVDeserializer::NotValid; 00357 return error; 00358 } 00359 00360 offset += til._length; 00361 00362 if(offset < tlv_size) { 00363 error = deserialize_resource_instances(tlv, tlv_size, offset, resource, operation, update_value); 00364 } 00365 return error; 00366 } 00367 00368 bool M2MTLVDeserializer::is_object_instance(const uint8_t *tlv, uint32_t offset) 00369 { 00370 bool ret = false; 00371 if (tlv) { 00372 uint8_t value = tlv[offset]; 00373 ret = (TYPE_OBJECT_INSTANCE == (value & TYPE_RESOURCE)); 00374 } 00375 return ret; 00376 } 00377 00378 uint16_t M2MTLVDeserializer::instance_id(const uint8_t *tlv) 00379 { 00380 TypeIdLength til(tlv, 0); 00381 til.deserialize(); 00382 uint16_t id = til._id; 00383 return id; 00384 } 00385 00386 bool M2MTLVDeserializer::is_resource(const uint8_t *tlv, uint32_t offset) 00387 { 00388 bool ret = false; 00389 if (tlv) { 00390 ret = (TYPE_RESOURCE == (tlv[offset] & TYPE_RESOURCE)); 00391 } 00392 return ret; 00393 } 00394 00395 bool M2MTLVDeserializer::is_multiple_resource(const uint8_t *tlv, uint32_t offset) 00396 { 00397 bool ret = false; 00398 if (tlv) { 00399 ret = (TYPE_MULTIPLE_RESOURCE == (tlv[offset] & TYPE_RESOURCE)); 00400 } 00401 return ret; 00402 } 00403 00404 bool M2MTLVDeserializer::is_resource_instance(const uint8_t *tlv, uint32_t offset) 00405 { 00406 bool ret = false; 00407 if (tlv) { 00408 ret = (TYPE_RESOURCE_INSTANCE == (tlv[offset] & TYPE_RESOURCE)); 00409 } 00410 return ret; 00411 } 00412 00413 bool M2MTLVDeserializer::set_resource_instance_value(M2MResourceBase *res, const uint8_t *tlv, const uint32_t size) 00414 { 00415 bool success = true; 00416 switch (res->resource_instance_type()) { 00417 case M2MResourceBase::INTEGER: 00418 case M2MResourceBase::BOOLEAN: 00419 case M2MResourceBase::TIME: 00420 { 00421 int64_t value = String::convert_array_to_integer(tlv, size); 00422 if (!res->set_value(value)) { 00423 success = false; 00424 } 00425 break; 00426 // Todo! implement conversion for other types as well 00427 } 00428 case M2MResourceBase::STRING: 00429 case M2MResourceBase::OPAQUE: 00430 case M2MResourceBase::OBJLINK: 00431 if (!res->set_value(tlv, size)) { 00432 success = false; 00433 } 00434 break; 00435 case M2MResourceBase::FLOAT: 00436 { 00437 uint32_t value = common_read_32_bit(tlv); 00438 if (!res->set_value_float(*(float*)&value)) { 00439 success = false; 00440 } 00441 break; 00442 } 00443 default: 00444 success = false; 00445 break; 00446 } 00447 00448 return success; 00449 } 00450 00451 void M2MTLVDeserializer::remove_resources(const uint8_t *tlv, 00452 uint32_t tlv_size, 00453 M2MObjectInstance &object_instance, 00454 uint32_t offset_size) 00455 { 00456 tr_debug("M2MTLVDeserializer::remove_resources"); 00457 uint32_t offset = offset_size; 00458 const M2MResourceList &list = object_instance.resources(); 00459 M2MResourceList::const_iterator it; 00460 00461 it = list.begin(); 00462 for (; it!=list.end();) { 00463 bool found = false; 00464 while(offset < tlv_size) { 00465 TypeIdLength til(tlv, offset); 00466 til.deserialize(); 00467 offset = til._offset; 00468 offset += til._length; 00469 if((*it)->name_id() == til._id){ 00470 offset = offset_size; 00471 found = true; 00472 break; 00473 } 00474 } 00475 offset = offset_size; 00476 00477 // Remove resource if not part of the TLV message 00478 if (!found) { 00479 tr_debug("M2MTLVDeserializer::remove_resources - remove resource %" PRId32, (*it)->name_id()); 00480 object_instance.remove_resource((*it)->name()); 00481 } else { 00482 ++it; 00483 } 00484 } 00485 } 00486 00487 void M2MTLVDeserializer::remove_resource_instances(const uint8_t *tlv, 00488 uint32_t tlv_size, 00489 M2MResource &resource, 00490 uint32_t offset_size) 00491 { 00492 tr_debug("M2MTLVDeserializer::remove_resource_instances"); 00493 uint32_t offset = offset_size; 00494 const M2MResourceInstanceList &list = resource.resource_instances(); 00495 M2MResourceInstanceList::const_iterator it; 00496 it = list.begin(); 00497 00498 for (; it!=list.end();) { 00499 bool found = false; 00500 while (offset < tlv_size) { 00501 TypeIdLength til(tlv, offset); 00502 til.deserialize(); 00503 offset = til._offset; 00504 offset += til._length; 00505 if ((*it)->instance_id() == til._id){ 00506 offset = offset_size; 00507 found = true; 00508 break; 00509 } 00510 } 00511 offset = offset_size; 00512 00513 // Remove resource instance if not part of the TLV message 00514 if (!found) { 00515 tr_debug("M2MTLVDeserializer::remove_resource_instances - remove resource instance %d", (*it)->instance_id()); 00516 resource.remove_resource_instance((*it)->instance_id()); 00517 } else { 00518 ++it; 00519 } 00520 } 00521 } 00522 00523 TypeIdLength::TypeIdLength(const uint8_t *tlv, uint32_t offset) 00524 : _tlv(tlv), _offset(offset), _type(tlv[offset] & 0xC0), _id(0), _length(0) 00525 { 00526 } 00527 00528 void TypeIdLength::deserialize() 00529 { 00530 uint32_t idLength = _tlv[_offset] & ID16; 00531 uint32_t lengthType = _tlv[_offset] & LENGTH24; 00532 if (0 == lengthType) { 00533 _length = _tlv[_offset] & 0x07; 00534 } 00535 _offset++; 00536 00537 deserialiseID(idLength); 00538 deserialiseLength(lengthType); 00539 } 00540 00541 void TypeIdLength::deserialiseID(uint32_t idLength) 00542 { 00543 _id = _tlv[_offset++] & 0xFF; 00544 if (ID16 == idLength) { 00545 _id = (_id << 8) + (_tlv[_offset++] & 0xFF); 00546 } 00547 } 00548 00549 void TypeIdLength::deserialiseLength(uint32_t lengthType) 00550 { 00551 if (lengthType > 0) { 00552 _length = _tlv[_offset++] & 0xFF; 00553 } 00554 if (lengthType > LENGTH8) { 00555 _length = (_length << 8) + (_tlv[_offset++] & 0xFF); 00556 } 00557 if (lengthType > LENGTH16) { 00558 _length = (_length << 8) + (_tlv[_offset++] & 0xFF); 00559 } 00560 }
Generated on Mon Aug 29 2022 19:53:40 by
