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