Ram Gandikota / Mbed OS ABCD
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mbase.cpp Source File

m2mbase.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 
00017 #include "mbed-client/m2mbase.h"
00018 #include "mbed-client/m2mobservationhandler.h"
00019 #include "mbed-client/m2mconstants.h"
00020 #include "mbed-client/m2mtimer.h"
00021 
00022 #include "mbed-client/m2mobject.h"
00023 #include "mbed-client/m2mobjectinstance.h"
00024 #include "mbed-client/m2mresource.h"
00025 
00026 #include "include/m2mreporthandler.h"
00027 #include "include/nsdlaccesshelper.h"
00028 #include "mbed-trace/mbed_trace.h"
00029 #include <assert.h>
00030 #include <ctype.h>
00031 #include <string.h>
00032 #include <stdlib.h>
00033 
00034 #define TRACE_GROUP "mClt"
00035 
00036 M2MBase::M2MBase(const String& resource_name,
00037                  M2MBase::Mode mode,
00038                  const String &resource_type,
00039                  char *path,
00040                  bool external_blockwise_store)
00041 :
00042   _sn_resource(NULL),
00043   _report_handler(NULL),
00044   _observation_handler(NULL),
00045   _token(NULL),
00046   _function_pointer(NULL),
00047   _value_updated_callback(NULL),
00048   _observation_number(0),
00049   _token_length(0),
00050   _observation_level(M2MBase::None),
00051   _is_under_observation(false)
00052 {
00053     // Checking the name length properly, i.e returning error is impossible from constructor without exceptions
00054     assert(resource_name.length() <= MAX_ALLOWED_STRING_LENGTH);
00055 
00056     _sn_resource = (lwm2m_parameters_s*)memory_alloc(sizeof(lwm2m_parameters_s));
00057     if(_sn_resource) {
00058         memset(_sn_resource, 0, sizeof(lwm2m_parameters_s));
00059         _sn_resource->free_on_delete = true;
00060         _sn_resource->dynamic_resource_params =
00061                 (sn_nsdl_dynamic_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_dynamic_resource_parameters_s));
00062         if(_sn_resource->dynamic_resource_params) {
00063             memset(_sn_resource->dynamic_resource_params,
00064                    0, sizeof(sn_nsdl_dynamic_resource_parameters_s));
00065             _sn_resource->dynamic_resource_params->static_resource_parameters =
00066                     (sn_nsdl_static_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_static_resource_parameters_s));
00067 
00068             // Set callback function in case of dynamic resource
00069             if (M2MBase::Dynamic == mode) {
00070                 _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback;
00071             }
00072 
00073             if(_sn_resource->dynamic_resource_params->static_resource_parameters) {
00074                 // Cast const away to able to compile using MEMORY_OPTIMIZED_API flag
00075                 sn_nsdl_static_resource_parameters_s *params =
00076                         const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters);
00077                 memset(params, 0, sizeof(sn_nsdl_static_resource_parameters_s));
00078                 const size_t len = strlen(resource_type.c_str());
00079                 if (len > 0) {
00080                     params->resource_type_ptr = (char*)
00081                             alloc_string_copy((uint8_t*) resource_type.c_str(), len);
00082                 }
00083                 params->path = (uint8_t*)path;
00084                 params->pathlen = strlen(path);
00085 
00086 
00087                 params->mode = (const uint8_t)mode;
00088                 params->free_on_delete = true;
00089                 params->external_memory_block = external_blockwise_store;
00090                 _sn_resource->dynamic_resource_params->static_resource_parameters = params;
00091             }
00092         }
00093 
00094         _sn_resource->name = stringdup((char*)resource_name.c_str());
00095         _sn_resource->dynamic_resource_params->publish_uri = true;
00096         _sn_resource->dynamic_resource_params->free_on_delete = true;
00097 
00098         if(is_integer(resource_name) && resource_name.size() <= MAX_ALLOWED_STRING_LENGTH) {
00099             _sn_resource->name_id = strtoul(resource_name.c_str(), NULL, 10);
00100             if(_sn_resource->name_id > 65535){
00101                 _sn_resource->name_id = -1;
00102             }
00103         } else {
00104             _sn_resource->name_id = -1;
00105         }
00106     }
00107 }
00108 
00109 M2MBase::M2MBase(const lwm2m_parameters_s *s):
00110     _sn_resource((lwm2m_parameters_s*) s),
00111     _report_handler(NULL),
00112     _observation_handler(NULL),
00113     _token(NULL),
00114     _function_pointer(NULL),
00115     _value_updated_callback(NULL),
00116     _observation_number(0),
00117     _token_length(0),
00118     _observation_level(M2MBase::None),
00119     _is_under_observation(false)
00120 {
00121     // Set callback function in case of dynamic resource
00122     if (M2MBase::Dynamic == _sn_resource->dynamic_resource_params->static_resource_parameters->mode) {
00123         _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback;
00124     }
00125 }
00126 
00127 M2MBase::~M2MBase()
00128 {
00129     delete _report_handler;
00130     free_resources();
00131     free(_token);
00132     delete _function_pointer;
00133     delete _value_updated_callback;
00134 }
00135 
00136 char* M2MBase::create_path(const M2MObject &parent, uint16_t object_instance)
00137 {
00138     StringBuffer<5> obj_inst_id;
00139     obj_inst_id.append_int(object_instance);
00140 
00141     return create_path(parent, obj_inst_id.c_str());
00142 }
00143 
00144 char* M2MBase::create_path(const M2MObject &parent, const char *name)
00145 {
00146     char * result = NULL;
00147     StringBuffer<(MAX_NAME_SIZE * 2 + (2 + 1))> path;
00148 
00149     const char* obj_name = parent.name();
00150 
00151     // XXX: ensure space
00152     path.append(obj_name);
00153     path.append('/');
00154     path.append(name);
00155 
00156     result = stringdup(path.c_str());
00157     return result;
00158 }
00159 
00160 char* M2MBase::create_path(const M2MResource &parent, uint16_t resource_instance)
00161 {
00162     StringBuffer<5> res_inst;
00163     res_inst.append_int(resource_instance);
00164 
00165     return create_path(parent, res_inst.c_str());
00166 }
00167 
00168 char* M2MBase::create_path(const M2MResource &parent, const char *name)
00169 {
00170     char * result = NULL;
00171     StringBuffer<(MAX_NAME_SIZE * 4 + (3 + 1))> path;
00172     M2MObjectInstance& parent_object_instance = parent.get_parent_object_instance();
00173     M2MObject& parent_object = parent_object_instance.get_parent_object();
00174 
00175     const char* obj_name = parent_object.name();
00176 
00177     // Note: the parent_object_instance.name() contains name of its parent object, not the name of instance,
00178     // so we need to skip that here
00179     const uint16_t obj_inst_id = parent_object_instance.instance_id();
00180 
00181     const char* resource_name = parent.name();
00182 
00183     // XXX: ensure space
00184     path.append(obj_name);
00185     path.append('/');
00186     path.append_int(obj_inst_id);
00187     path.append('/');
00188     path.append(resource_name);
00189     path.append('/');
00190     path.append(name);
00191 
00192     result = stringdup(path.c_str());
00193     return result;
00194 }
00195 
00196 char* M2MBase::create_path(const M2MObjectInstance &parent, const char *name)
00197 {
00198     char * result = NULL;
00199     StringBuffer<(MAX_NAME_SIZE * 3 + (2 + 1))> path;
00200     M2MObject& parent_object = parent.get_parent_object();
00201 
00202     const char* obj_name = parent_object.name();
00203     // Note: the parent_object_instance.name() contains name of its parent object, not the name of instance,
00204     // so we need to skip that here
00205     const uint16_t obj_inst_id = parent.instance_id();
00206 
00207     // XXX: ensure space
00208     path.append(obj_name);
00209     path.append('/');
00210     path.append_int(obj_inst_id);
00211     path.append('/');
00212     path.append(name);
00213 
00214     result = stringdup(path.c_str());
00215     return result;
00216 }
00217 
00218 
00219 void M2MBase::set_operation(M2MBase::Operation opr)
00220 {
00221     // If the mode is Static, there is only GET_ALLOWED supported.
00222     if(M2MBase::Static == mode()) {
00223         _sn_resource->dynamic_resource_params->access = M2MBase::GET_ALLOWED;
00224     } else {
00225         _sn_resource->dynamic_resource_params->access = opr;
00226     }
00227 }
00228 
00229 #ifndef MEMORY_OPTIMIZED_API
00230 void M2MBase::set_interface_description(const char *desc)
00231 {
00232     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00233     free(_sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr);
00234     _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr = NULL;
00235     const size_t len = strlen(desc);
00236     if (len > 0 ) {
00237         _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr =
00238                 (char*)alloc_string_copy((uint8_t*) desc, len);
00239     }
00240 }
00241 
00242 void M2MBase::set_interface_description(const String &desc)
00243 {
00244     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00245     set_interface_description(desc.c_str());
00246 }
00247 
00248 void M2MBase::set_resource_type(const String &res_type)
00249 {
00250     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00251     set_resource_type(res_type.c_str());
00252 }
00253 
00254 void M2MBase::set_resource_type(const char *res_type)
00255 {
00256     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00257     free(_sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr);
00258     _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = NULL;
00259     const size_t len = strlen(res_type);
00260     if (len > 0) {
00261         _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = (char*)
00262                 alloc_string_copy((uint8_t*) res_type, len);
00263     }
00264 }
00265 #endif
00266 
00267 void M2MBase::set_coap_content_type(const uint8_t con_type)
00268 {
00269     _sn_resource->dynamic_resource_params->coap_content_type = con_type;
00270 }
00271 
00272 void M2MBase::set_observable(bool observable)
00273 {
00274     _sn_resource->dynamic_resource_params->observable = observable;
00275 }
00276 
00277 void M2MBase::add_observation_level(M2MBase::Observation obs_level)
00278 {
00279     _observation_level = (M2MBase::Observation)(_observation_level | obs_level);
00280 }
00281 
00282 void M2MBase::remove_observation_level(M2MBase::Observation obs_level)
00283 {
00284     _observation_level = (M2MBase::Observation)(_observation_level & ~obs_level);
00285 }
00286 
00287 void M2MBase::set_observation_handler(M2MObservationHandler *handler)
00288 {
00289     tr_debug("M2MBase::set_observation_handler - handler: 0x%x", handler);
00290     _observation_handler = handler;
00291 }
00292 
00293 
00294 void M2MBase::set_under_observation(bool observed,
00295                                     M2MObservationHandler *handler)
00296 {
00297     tr_debug("M2MBase::set_under_observation - observed: %d", observed);
00298     tr_debug("M2MBase::set_under_observation - base_type: %d", base_type());
00299     _is_under_observation = observed;
00300     _observation_handler = handler;
00301     if (handler) {
00302         if (base_type() != M2MBase::ResourceInstance) {
00303             // Create report handler only if it does not exist and one wants observation
00304             // This saves 76 bytes of memory on most usual case.
00305             if (observed) {
00306                 if(!_report_handler) {
00307                     _report_handler = new M2MReportHandler(*this);
00308                 }
00309             }
00310             if (_report_handler) {
00311                 _report_handler->set_under_observation(observed);
00312             }
00313         }
00314     } else {
00315         delete _report_handler;
00316         _report_handler = NULL;
00317     }
00318 }
00319 
00320 void M2MBase::set_observation_token(const uint8_t *token, const uint8_t length)
00321 {
00322      free(_token);
00323      _token = NULL;
00324      _token_length = 0;
00325 
00326     if( token != NULL && length > 0 ) {
00327         _token = alloc_string_copy((uint8_t *)token, length);
00328         if(_token) {
00329             _token_length = length;
00330         }
00331     }
00332 }
00333 
00334 void M2MBase::set_instance_id(const uint16_t inst_id)
00335 {
00336     _sn_resource->instance_id = inst_id;
00337 }
00338 
00339 void M2MBase::set_observation_number(const uint16_t /*observation_number*/)
00340 {
00341 }
00342 
00343 void M2MBase::set_max_age(const uint32_t max_age)
00344 {
00345     _sn_resource->max_age = max_age;
00346 }
00347 
00348 M2MBase::BaseType M2MBase::base_type() const
00349 {
00350     return (M2MBase::BaseType)_sn_resource->base_type;
00351 }
00352 
00353 M2MBase::Operation M2MBase::operation() const
00354 {
00355     return (M2MBase::Operation)_sn_resource->dynamic_resource_params->access;
00356 }
00357 
00358 const char* M2MBase::name() const
00359 {
00360     return _sn_resource->name;
00361 }
00362 
00363 int32_t M2MBase::name_id() const
00364 {
00365     return _sn_resource->name_id;
00366 }
00367 
00368 uint16_t M2MBase::instance_id() const
00369 {
00370     return _sn_resource->instance_id;
00371 }
00372 
00373 const char* M2MBase::interface_description() const
00374 {
00375     return (reinterpret_cast<char*>(
00376         _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr));
00377 }
00378 
00379 const char* M2MBase::resource_type() const
00380 {
00381     return (reinterpret_cast<char*>(
00382         _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr));
00383 }
00384 
00385 const char* M2MBase::uri_path() const
00386 {
00387     return (reinterpret_cast<char*>(
00388         _sn_resource->dynamic_resource_params->static_resource_parameters->path));
00389 }
00390 
00391 uint8_t M2MBase::coap_content_type() const
00392 {
00393     return _sn_resource->dynamic_resource_params->coap_content_type;
00394 }
00395 
00396 bool M2MBase::is_observable() const
00397 {
00398     return _sn_resource->dynamic_resource_params->observable;
00399 }
00400 
00401 M2MBase::Observation M2MBase::observation_level() const
00402 {
00403     return _observation_level;
00404 }
00405 
00406 void M2MBase::get_observation_token(uint8_t *&token, uint32_t &token_length)
00407 {
00408     token_length = 0;
00409     free(token);
00410     if (_token) {
00411         token = alloc_string_copy((uint8_t *)_token, _token_length);
00412         if(token) {
00413             token_length = _token_length;
00414         }
00415     }
00416 }
00417 
00418 M2MBase::Mode M2MBase::mode() const
00419 {
00420     return (M2MBase::Mode)_sn_resource->dynamic_resource_params->static_resource_parameters->mode;
00421 }
00422 
00423 uint16_t M2MBase::observation_number() const
00424 {
00425     return _observation_number;
00426 }
00427 
00428 uint32_t M2MBase::max_age() const
00429 {
00430     return _sn_resource->max_age;
00431 }
00432 
00433 bool M2MBase::handle_observation_attribute(const char *query)
00434 {
00435     tr_debug("M2MBase::handle_observation_attribute - under observation(%d)", is_under_observation());
00436     bool success = false;
00437     // Create handler if not already exists. Client must able to parse write attributes even when
00438     // observation is not yet set
00439     if (!_report_handler) {
00440         _report_handler = new M2MReportHandler(*this);
00441     }
00442 
00443     success = _report_handler->parse_notification_attribute(query,base_type());
00444     if (success) {
00445         if (is_under_observation()) {
00446             _report_handler->set_under_observation(true);
00447         }
00448      } else {
00449         _report_handler->set_default_values();
00450     }
00451     return success;
00452 }
00453 
00454 void M2MBase::observation_to_be_sent(m2m::Vector<uint16_t> changed_instance_ids, bool send_object)
00455 {
00456     //TODO: Move this to M2MResourceInstance
00457     if(_observation_handler) {
00458        _observation_number++;
00459        _observation_handler->observation_to_be_sent(this,
00460                                                     _observation_number,
00461                                                     changed_instance_ids,
00462                                                     send_object);
00463     }
00464 }
00465 
00466 void M2MBase::set_base_type(M2MBase::BaseType type)
00467 {
00468     assert(_sn_resource->free_on_delete);
00469     _sn_resource->base_type = type;
00470 }
00471 
00472 sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/,
00473                                            sn_coap_hdr_s */*received_coap_header*/,
00474                                            M2MObservationHandler */*observation_handler*/)
00475 {
00476     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00477     return NULL;
00478 }
00479 
00480 sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/,
00481                                            sn_coap_hdr_s */*received_coap_header*/,
00482                                            M2MObservationHandler */*observation_handler*/,
00483                                            bool &)
00484 {
00485     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00486     return NULL;
00487 }
00488 
00489 sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/,
00490                                             sn_coap_hdr_s */*received_coap_header*/,
00491                                             M2MObservationHandler */*observation_handler*/,
00492                                             bool &,
00493                                             sn_nsdl_addr_s *)
00494 {
00495     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00496     return NULL;
00497 }
00498 
00499 void *M2MBase::memory_alloc(uint32_t size)
00500 {
00501     if(size)
00502         return malloc(size);
00503     else
00504         return 0;
00505 }
00506 
00507 void M2MBase::memory_free(void *ptr)
00508 {
00509     free(ptr);
00510 }
00511 
00512 char* M2MBase::alloc_string_copy(const char* source)
00513 {
00514     assert(source != NULL);
00515 
00516     // Note: the armcc's libc does not have strdup, so we need to implement it here
00517     const size_t len = strlen(source);
00518 
00519     return (char*)alloc_string_copy((uint8_t*)source, len);
00520 }
00521 
00522 uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size)
00523 {
00524     assert(source != NULL);
00525 
00526     uint8_t* result = (uint8_t*)memory_alloc(size + 1);
00527     if (result) {
00528         memcpy(result, source, size);
00529         result[size] = '\0';
00530     }
00531     return result;
00532 }
00533 
00534 uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size)
00535 {
00536     assert(source != NULL);
00537 
00538     uint8_t* result = (uint8_t*)memory_alloc(size);
00539     if (result) {
00540         memcpy(result, source, size);
00541     }
00542     return result;
00543 }
00544 
00545 bool M2MBase::validate_string_length(const String &string, size_t min_length, size_t max_length)
00546 {
00547     bool valid = false;
00548 
00549     const size_t len = string.length();
00550     if ((len >= min_length) && (len <= max_length)) {
00551         valid = true;
00552     }
00553 
00554     return valid;
00555 }
00556 
00557 bool M2MBase::validate_string_length(const char* string, size_t min_length, size_t max_length)
00558 {
00559     bool valid = false;
00560 
00561     if (string != NULL) {
00562         const size_t len = strlen(string);
00563         if ((len >= min_length) && (len <= max_length)) {
00564             valid = true;
00565         }
00566     }
00567 
00568     return valid;
00569 }
00570 
00571 M2MReportHandler* M2MBase::create_report_handler()
00572 {
00573     if (!_report_handler) {
00574         _report_handler = new M2MReportHandler(*this);
00575     }
00576     return _report_handler;
00577 }
00578 
00579 M2MReportHandler* M2MBase::report_handler()
00580 {
00581     return _report_handler;
00582 }
00583 
00584 M2MObservationHandler* M2MBase::observation_handler()
00585 {
00586     return _observation_handler;
00587 }
00588 
00589 void M2MBase::set_register_uri(bool register_uri)
00590 {
00591     _sn_resource->dynamic_resource_params->publish_uri = register_uri;
00592 }
00593 
00594 bool M2MBase::register_uri()
00595 {
00596     return _sn_resource->dynamic_resource_params->publish_uri;
00597 }
00598 
00599 bool M2MBase::is_integer(const String &value)
00600 {
00601     const char *s = value.c_str();
00602     if(value.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
00603         return false;
00604     }
00605     char * p;
00606     strtol(value.c_str(), &p, 10);
00607     return (*p == 0);
00608 }
00609 
00610 bool M2MBase::is_integer(const char *value)
00611 {
00612     assert(value != NULL);
00613 
00614     if((strlen(value) < 1) || ((!isdigit(value[0])) && (value[0] != '-') && (value[0] != '+'))) {
00615         return false;
00616     }
00617     char * p;
00618     strtol(value, &p, 10);
00619     return (*p == 0);
00620 }
00621 
00622 bool M2MBase::is_under_observation() const
00623 {
00624     return _is_under_observation;
00625 }
00626 
00627 void M2MBase::set_value_updated_function(value_updated_callback  callback)
00628 {
00629     delete _value_updated_callback;
00630     // XXX: create a copy of the copy of callback object. Perhaps it would better to
00631     // give a reference as parameter and just store that, as it would save some memory.
00632     _value_updated_callback = new value_updated_callback (callback);
00633 }
00634 
00635 void M2MBase::set_value_updated_function(value_updated_callback2 callback)
00636 {
00637     delete _function_pointer;
00638     _function_pointer = new FP1<void, const char*> (callback);
00639     set_value_updated_function(value_updated_callback (_function_pointer,
00640                                                       &FP1<void, const char*>::call));
00641 }
00642 
00643 bool M2MBase::is_value_updated_function_set()
00644 {
00645     return (_value_updated_callback) ? true : false;
00646 }
00647 
00648 void M2MBase::execute_value_updated(const String& name)
00649 {
00650     if(_value_updated_callback) {
00651         (*_value_updated_callback)(name.c_str());
00652     }
00653 }
00654 
00655 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE> &buffer, const char *s1, uint16_t i1, const char *s2, uint16_t i2)
00656 {
00657 
00658     if(!buffer.ensure_space(strlen(s1) + strlen(s2) + (MAX_INSTANCE_SIZE * 2) + 3 + 1)){
00659         return false;
00660     }
00661 
00662     buffer.append(s1);
00663     buffer.append('/');
00664     buffer.append_int(i1);
00665     buffer.append('/');
00666     buffer.append(s2);
00667     buffer.append('/');
00668     buffer.append_int(i2);
00669 
00670     return true;
00671 
00672 }
00673 
00674 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_2> &buffer, const char *s1, uint16_t i1, const char *s2)
00675 {
00676     if(!buffer.ensure_space(strlen(s1) + strlen(s2) + MAX_INSTANCE_SIZE + 2 + 1)){
00677         return false;
00678     }
00679 
00680     buffer.append(s1);
00681     buffer.append('/');
00682     buffer.append_int(i1);
00683     buffer.append('/');
00684     buffer.append(s2);
00685 
00686     return true;
00687 }
00688 
00689 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_3> &buffer, const char *s1, uint16_t i1, uint16_t i2)
00690 {
00691     if(!buffer.ensure_space(strlen(s1) + (MAX_INSTANCE_SIZE * 2) + 2 + 1)){
00692         return false;
00693     }
00694 
00695     buffer.append(s1);
00696     buffer.append('/');
00697     buffer.append_int(i1);
00698     buffer.append('/');
00699     buffer.append_int(i2);
00700 
00701     return true;
00702 }
00703 
00704 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_4> &buffer, const char *s1, uint16_t i1)
00705 {
00706     if(!buffer.ensure_space(strlen(s1) + MAX_INSTANCE_SIZE + 1 + 1)){
00707         return false;
00708     }
00709 
00710     buffer.append(s1);
00711     buffer.append('/');
00712     buffer.append_int(i1);
00713 
00714     return true;
00715 }
00716 
00717 char* M2MBase::stringdup(const char* src)
00718 {
00719     assert(src != NULL);
00720 
00721     const size_t len = strlen(src) + 1;
00722 
00723     char *dest = (char*)malloc(len);
00724 
00725     if (dest) {
00726         memcpy(dest, src, len);
00727     }
00728     return dest;
00729 }
00730 
00731 void M2MBase::free_resources()
00732 {
00733     // remove the nsdl structures from the nsdlinterface's lists.
00734     if (_observation_handler) {
00735         _observation_handler->resource_to_be_deleted(this);
00736     }
00737 
00738     if (_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete) {
00739         sn_nsdl_static_resource_parameters_s *params =
00740                 const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters);
00741 
00742         free(params->path);
00743         free(params->resource);
00744         free(params->resource_type_ptr);
00745         free(params->interface_description_ptr);
00746         free(params);
00747     }
00748     if (_sn_resource->dynamic_resource_params->free_on_delete) {
00749         free(_sn_resource->dynamic_resource_params);
00750     }
00751 
00752     if (_sn_resource->free_on_delete) {
00753         free(_sn_resource->name);
00754         free(_sn_resource);
00755     }
00756 }
00757 
00758 size_t M2MBase::resource_name_length() const
00759 {
00760     return strlen(_sn_resource->name);
00761 }
00762 
00763 sn_nsdl_dynamic_resource_parameters_s* M2MBase::get_nsdl_resource()
00764 {
00765     return _sn_resource->dynamic_resource_params;
00766 }