Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
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