Simple interface for Mbed Cloud Client

Dependents:  

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 "include/m2mcallbackstorage.h"
00029 #include "mbed-trace/mbed_trace.h"
00030 
00031 #include "sn_nsdl_lib.h"
00032 #include <assert.h>
00033 #include <ctype.h>
00034 #include <string.h>
00035 #include <stdlib.h>
00036 #include "common_functions.h"
00037 
00038 #define TRACE_GROUP "mClt"
00039 
00040 M2MBase::M2MBase(const String& resource_name,
00041                  M2MBase::Mode mode,
00042 #ifndef DISABLE_RESOURCE_TYPE
00043                  const String &resource_type,
00044 #endif
00045                  char *path,
00046                  bool external_blockwise_store,
00047                  bool multiple_instance,
00048                  M2MBase::DataType type)
00049 :
00050   _sn_resource(NULL),
00051   _report_handler(NULL)
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->multiple_instance = multiple_instance;
00061         _sn_resource->data_type = type;
00062         _sn_resource->dynamic_resource_params =
00063                 (sn_nsdl_dynamic_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_dynamic_resource_parameters_s));
00064         if(_sn_resource->dynamic_resource_params) {
00065             memset(_sn_resource->dynamic_resource_params,
00066                    0, sizeof(sn_nsdl_dynamic_resource_parameters_s));
00067             _sn_resource->dynamic_resource_params->static_resource_parameters =
00068                     (sn_nsdl_static_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_static_resource_parameters_s));
00069 
00070             // Set callback function in case of both dynamic and static resource
00071             _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback;
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 #ifndef RESOURCE_ATTRIBUTES_LIST
00081 #ifndef DISABLE_RESOURCE_TYPE
00082                     params->resource_type_ptr = (char*)alloc_string_copy((uint8_t*) resource_type.c_str(), len);
00083 #endif
00084 #else
00085                     sn_nsdl_attribute_item_s item;
00086                     item.attribute_name = ATTR_RESOURCE_TYPE;
00087                     item.value = (char*)alloc_string_copy((uint8_t*) resource_type.c_str(), len);
00088                     sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
00089 #endif
00090                 }
00091                 params->path = path;
00092                 params->mode = (unsigned)mode;
00093                 params->free_on_delete = true;
00094                 params->external_memory_block = external_blockwise_store;
00095                 _sn_resource->dynamic_resource_params->static_resource_parameters = params;
00096             }
00097         }
00098 
00099         if((!resource_name.empty())) {
00100             _sn_resource->identifier_int_type = false;
00101             _sn_resource->identifier.name = stringdup((char*)resource_name.c_str());
00102         } else {
00103             tr_debug("M2MBase::M2Mbase resource name is EMPTY ===========");
00104             _sn_resource->identifier_int_type = true;
00105             _sn_resource->identifier.instance_id = 0;
00106         }
00107         _sn_resource->dynamic_resource_params->publish_uri = true;
00108         _sn_resource->dynamic_resource_params->free_on_delete = true;
00109         _sn_resource->dynamic_resource_params->notification_status = NOTIFICATION_STATUS_INIT;
00110         _sn_resource->dynamic_resource_params->auto_observable = false;
00111     }
00112 }
00113 
00114 M2MBase::M2MBase(const lwm2m_parameters_s *s):
00115     _sn_resource((lwm2m_parameters_s*) s),
00116     _report_handler(NULL)
00117 {
00118     tr_debug("M2MBase::M2MBase(const lwm2m_parameters_s *s)");
00119     // Set callback function in case of both dynamic and static resource
00120     _sn_resource->dynamic_resource_params->sn_grs_dyn_res_callback = __nsdl_c_callback;
00121 }
00122 
00123 M2MBase::~M2MBase()
00124 {
00125     tr_debug("M2MBase::~M2MBase()");
00126     delete _report_handler;
00127 
00128     value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00129     delete callback;
00130 
00131     M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00132     M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
00133 }
00134 
00135 char* M2MBase::create_path_base(const M2MBase &parent, const char *name)
00136 {
00137     char * result = NULL;
00138     // Expectation is that every element can be MAX_NAME_SZE, + 4 /'s + \0
00139     StringBuffer<(MAX_NAME_SIZE * 4 + (4 + 1))> path;
00140     path.append(parent.uri_path());
00141     path.append('/');
00142     path.append(name);
00143     result = stringdup(path.c_str());
00144 
00145     return result;
00146 }
00147 
00148 char* M2MBase::create_path(const M2MObject &parent, uint16_t object_instance)
00149 {
00150     StringBuffer<6> obj_inst_id;
00151     obj_inst_id.append_int(object_instance);
00152 
00153     return create_path_base(parent, obj_inst_id.c_str());
00154 }
00155 
00156 char* M2MBase::create_path(const M2MObject &parent, const char *name)
00157 {
00158     return create_path_base(parent, name);
00159 }
00160 
00161 char* M2MBase::create_path(const M2MResource &parent, uint16_t resource_instance)
00162 {
00163     StringBuffer<6> res_inst;
00164     res_inst.append_int(resource_instance);
00165 
00166     return create_path_base(parent, res_inst.c_str());
00167 }
00168 
00169 char* M2MBase::create_path(const M2MResource &parent, const char *name)
00170 {
00171     return create_path_base(parent, name);
00172 }
00173 
00174 char* M2MBase::create_path(const M2MObjectInstance &parent, const char *name)
00175 {
00176     return create_path_base(parent, name);
00177 }
00178 
00179 void M2MBase::set_operation(M2MBase::Operation opr)
00180 {
00181     // If the mode is Static, there is only GET_ALLOWED supported.
00182     if(M2MBase::Static == mode()) {
00183         _sn_resource->dynamic_resource_params->access = M2MBase::GET_ALLOWED;
00184     } else {
00185         _sn_resource->dynamic_resource_params->access = opr;
00186     }
00187 }
00188 
00189 #ifndef RESOURCE_ATTRIBUTES_LIST
00190 #ifndef MEMORY_OPTIMIZED_API
00191 #ifndef DISABLE_INTERFACE_DESCRIPTION
00192 void M2MBase::set_interface_description(const char *desc)
00193 {
00194     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00195     free(_sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr);
00196     _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr = NULL;
00197     const size_t len = strlen(desc);
00198     if (len > 0 ) {
00199         _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr =
00200                 (char*)alloc_string_copy((uint8_t*) desc, len);
00201     }
00202 }
00203 
00204 void M2MBase::set_interface_description(const String &desc)
00205 {
00206     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00207     set_interface_description(desc.c_str());
00208 }
00209 #endif // DISABLE_INTERFACE_DESCRIPTION
00210 
00211 #ifndef DISABLE_RESOURCE_TYPE
00212 void M2MBase::set_resource_type(const String &res_type)
00213 {
00214     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00215     set_resource_type(res_type.c_str());
00216 }
00217 
00218 void M2MBase::set_resource_type(const char *res_type)
00219 {
00220     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00221     free(_sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr);
00222     _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = NULL;
00223     const size_t len = strlen(res_type);
00224     if (len > 0) {
00225         _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr = (char*)
00226                 alloc_string_copy((uint8_t*) res_type, len);
00227     }
00228 }
00229 #endif // DISABLE_RESOURCE_TYPE
00230 #endif //MEMORY_OPTIMIZED_API
00231 #else // RESOURCE_ATTRIBUTES_LIST
00232 void M2MBase::set_interface_description(const char *desc)
00233 {
00234     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00235     const size_t len = strlen(desc);
00236     if (len > 0 ) {
00237         sn_nsdl_attribute_item_s item;
00238         item.attribute_name = ATTR_INTERFACE_DESCRIPTION;
00239         item.value = (char*)alloc_string_copy((uint8_t*) desc, len);
00240         sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
00241     }
00242 }
00243 
00244 void M2MBase::set_interface_description(const String &desc)
00245 {
00246     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00247     set_interface_description(desc.c_str());
00248 }
00249 
00250 void M2MBase::set_resource_type(const String &res_type)
00251 {
00252     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00253     set_resource_type(res_type.c_str());
00254 }
00255 
00256 void M2MBase::set_resource_type(const char *res_type)
00257 {
00258     assert(_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete);
00259     const size_t len = strlen(res_type);
00260     if (len > 0) {
00261         sn_nsdl_attribute_item_s item;
00262         item.attribute_name = ATTR_RESOURCE_TYPE;
00263         item.value = (char*)alloc_string_copy((uint8_t*) res_type, len);
00264         sn_nsdl_set_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, &item);
00265     }
00266 }
00267 #endif // RESOURCE_ATTRIBUTES_LIST
00268 
00269 void M2MBase::set_coap_content_type(const uint16_t con_type)
00270 {
00271     _sn_resource->dynamic_resource_params->coap_content_type = con_type;
00272 }
00273 
00274 void M2MBase::set_observable(bool observable)
00275 {
00276     _sn_resource->dynamic_resource_params->observable = observable;
00277 }
00278 
00279 void M2MBase::set_auto_observable(bool auto_observable)
00280 {
00281     _sn_resource->dynamic_resource_params->auto_observable = auto_observable;
00282 }
00283 
00284 void M2MBase::add_observation_level(M2MBase::Observation obs_level)
00285 {
00286     if(_report_handler) {
00287         _report_handler->add_observation_level(obs_level);
00288     }
00289 }
00290 
00291 void M2MBase::remove_observation_level(M2MBase::Observation obs_level)
00292 {
00293     if(_report_handler) {
00294         _report_handler->remove_observation_level(obs_level);
00295     }
00296 }
00297 
00298 
00299 void M2MBase::set_under_observation(bool observed,
00300                                     M2MObservationHandler *handler)
00301 {
00302     tr_debug("M2MBase::set_under_observation - observed: %d", observed);
00303     tr_debug("M2MBase::set_under_observation - base_type: %d", base_type());
00304     if(_report_handler) {
00305         _report_handler->set_under_observation(observed);
00306     }
00307 
00308     set_observation_handler(handler);
00309 
00310     if (handler) {
00311         if (base_type() != M2MBase::ResourceInstance) {
00312             // Create report handler only if it does not exist and one wants observation
00313             // This saves 76 bytes of memory on most usual case.
00314             if (observed) {
00315                 if(!_report_handler) {
00316                     _report_handler = new M2MReportHandler(*this);
00317                 }
00318             }
00319             if (_report_handler) {
00320                 _report_handler->set_under_observation(observed);
00321             }
00322         }
00323     } else {
00324         delete _report_handler;
00325         _report_handler = NULL;
00326     }
00327 }
00328 
00329 void M2MBase::set_observation_token(const uint8_t *token, const uint8_t length)
00330 {
00331     if (_report_handler) {
00332         _report_handler->set_observation_token(token, length);
00333     }
00334 }
00335 
00336 void M2MBase::set_instance_id(const uint16_t inst_id)
00337 {
00338     _sn_resource->identifier_int_type = true;
00339     _sn_resource->identifier.instance_id = inst_id;
00340 }
00341 
00342 void M2MBase::set_max_age(const uint32_t max_age)
00343 {
00344     _sn_resource->max_age = max_age;
00345 }
00346 
00347 M2MBase::BaseType M2MBase::base_type() const
00348 {
00349     return (M2MBase::BaseType)_sn_resource->base_type;
00350 }
00351 
00352 M2MBase::Operation M2MBase::operation() const
00353 {
00354     return (M2MBase::Operation)_sn_resource->dynamic_resource_params->access;
00355 }
00356 
00357 const char* M2MBase::name() const
00358 {
00359     assert(_sn_resource->identifier_int_type == false);
00360     return _sn_resource->identifier.name;
00361 }
00362 
00363 int32_t M2MBase::name_id() const
00364 {
00365     int32_t name_id = -1;
00366     assert(_sn_resource->identifier_int_type == false);
00367     if(is_integer(_sn_resource->identifier.name) && strlen(_sn_resource->identifier.name) <= MAX_ALLOWED_STRING_LENGTH) {
00368         name_id = strtoul(_sn_resource->identifier.name, NULL, 10);
00369         if(name_id > 65535){
00370             name_id = -1;
00371         }
00372     }
00373     return name_id;
00374 }
00375 
00376 uint16_t M2MBase::instance_id() const
00377 {
00378     assert(_sn_resource->identifier_int_type == true);
00379     return _sn_resource->identifier.instance_id;
00380 }
00381 
00382 #ifndef RESOURCE_ATTRIBUTES_LIST
00383 #ifndef DISABLE_INTERFACE_DESCRIPTION
00384 const char* M2MBase::interface_description() const
00385 {
00386     return (reinterpret_cast<char*>(
00387         _sn_resource->dynamic_resource_params->static_resource_parameters->interface_description_ptr));
00388 }
00389 #endif
00390 
00391 #ifndef DISABLE_RESOURCE_TYPE
00392 const char* M2MBase::resource_type() const
00393 {
00394     return (reinterpret_cast<char*>(
00395         _sn_resource->dynamic_resource_params->static_resource_parameters->resource_type_ptr));
00396 }
00397 #endif
00398 #else // RESOURCE_ATTRIBUTES_LIST
00399 #ifndef DISABLE_INTERFACE_DESCRIPTION
00400 const char* M2MBase::interface_description() const
00401 {
00402     return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_INTERFACE_DESCRIPTION);
00403 }
00404 #endif
00405 
00406 #ifndef DISABLE_RESOURCE_TYPE
00407 const char* M2MBase::resource_type() const
00408 {
00409     return sn_nsdl_get_resource_attribute(_sn_resource->dynamic_resource_params->static_resource_parameters, ATTR_RESOURCE_TYPE);
00410 }
00411 #endif
00412 #endif // RESOURCE_ATTRIBUTES_LIST
00413 const char* M2MBase::uri_path() const
00414 {
00415     return (reinterpret_cast<char*>(
00416         _sn_resource->dynamic_resource_params->static_resource_parameters->path));
00417 }
00418 
00419 uint16_t M2MBase::coap_content_type() const
00420 {
00421     return _sn_resource->dynamic_resource_params->coap_content_type;
00422 }
00423 
00424 bool M2MBase::is_observable() const
00425 {
00426     if (_sn_resource->dynamic_resource_params->auto_observable) {
00427         return true;
00428     } else {
00429         return _sn_resource->dynamic_resource_params->observable;
00430     }
00431 }
00432 
00433 M2MBase::Observation M2MBase::observation_level() const
00434 {
00435     M2MBase::Observation obs_level = M2MBase::None;
00436     if(_report_handler) {
00437         obs_level = _report_handler->observation_level();
00438     }
00439     return obs_level;
00440 }
00441 
00442 void M2MBase::get_observation_token(uint8_t *token, uint8_t &token_length) const
00443 {
00444     if(_report_handler) {
00445         _report_handler->get_observation_token(token, token_length);
00446     }
00447 }
00448 
00449 M2MBase::Mode M2MBase::mode() const
00450 {
00451     return (M2MBase::Mode)_sn_resource->dynamic_resource_params->static_resource_parameters->mode;
00452 }
00453 
00454 uint16_t M2MBase::observation_number() const
00455 {
00456     uint16_t obs_number = 0;
00457     if(_report_handler) {
00458         obs_number = _report_handler->observation_number();
00459     }
00460     return obs_number;
00461 }
00462 
00463 uint32_t M2MBase::max_age() const
00464 {
00465     return _sn_resource->max_age;
00466 }
00467 
00468 bool M2MBase::handle_observation_attribute(const char *query)
00469 {
00470     tr_debug("M2MBase::handle_observation_attribute - under observation(%d)", is_under_observation());
00471     bool success = false;
00472     // Create handler if not already exists. Client must able to parse write attributes even when
00473     // observation is not yet set
00474     if (!_report_handler) {
00475         _report_handler = new M2MReportHandler(*this);
00476     }
00477 
00478     success = _report_handler->parse_notification_attribute(query,base_type());
00479     if (success) {
00480         if (is_under_observation()) {
00481             _report_handler->set_under_observation(true);
00482         }
00483      } else {
00484         _report_handler->set_default_values();
00485     }
00486     return success;
00487 }
00488 
00489 void M2MBase::observation_to_be_sent(const m2m::Vector<uint16_t> &changed_instance_ids,
00490                                      uint16_t obs_number,
00491                                      bool send_object)
00492 {
00493     //TODO: Move this to M2MResourceInstance
00494     M2MObservationHandler *obs_handler = observation_handler();
00495     if (obs_handler) {
00496         obs_handler->observation_to_be_sent(this,
00497                                             obs_number,
00498                                             changed_instance_ids,
00499                                             send_object);
00500     }
00501 }
00502 
00503 void M2MBase::set_base_type(M2MBase::BaseType type)
00504 {
00505     assert(_sn_resource->free_on_delete);
00506     _sn_resource->base_type = type;
00507 }
00508 
00509 sn_coap_hdr_s* M2MBase::handle_get_request(nsdl_s */*nsdl*/,
00510                                            sn_coap_hdr_s */*received_coap_header*/,
00511                                            M2MObservationHandler */*observation_handler*/)
00512 {
00513     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00514     return NULL;
00515 }
00516 
00517 sn_coap_hdr_s* M2MBase::handle_put_request(nsdl_s */*nsdl*/,
00518                                            sn_coap_hdr_s */*received_coap_header*/,
00519                                            M2MObservationHandler */*observation_handler*/,
00520                                            bool &)
00521 {
00522     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00523     return NULL;
00524 }
00525 
00526 sn_coap_hdr_s* M2MBase::handle_post_request(nsdl_s */*nsdl*/,
00527                                             sn_coap_hdr_s */*received_coap_header*/,
00528                                             M2MObservationHandler */*observation_handler*/,
00529                                             bool &,
00530                                             sn_nsdl_addr_s *)
00531 {
00532     //Handled in M2MResource, M2MObjectInstance and M2MObject classes
00533     return NULL;
00534 }
00535 
00536 void *M2MBase::memory_alloc(uint32_t size)
00537 {
00538     if(size)
00539         return malloc(size);
00540     else
00541         return 0;
00542 }
00543 
00544 void M2MBase::memory_free(void *ptr)
00545 {
00546     free(ptr);
00547 }
00548 
00549 char* M2MBase::alloc_string_copy(const char* source)
00550 {
00551     assert(source != NULL);
00552 
00553     // Note: the armcc's libc does not have strdup, so we need to implement it here
00554     const size_t len = strlen(source);
00555 
00556     return (char*)alloc_string_copy((uint8_t*)source, len);
00557 }
00558 
00559 uint8_t* M2MBase::alloc_string_copy(const uint8_t* source, uint32_t size)
00560 {
00561     assert(source != NULL);
00562 
00563     uint8_t* result = (uint8_t*)memory_alloc(size + 1);
00564     if (result) {
00565         memcpy(result, source, size);
00566         result[size] = '\0';
00567     }
00568     return result;
00569 }
00570 
00571 uint8_t* M2MBase::alloc_copy(const uint8_t* source, uint32_t size)
00572 {
00573     assert(source != NULL);
00574 
00575     uint8_t* result = (uint8_t*)memory_alloc(size);
00576     if (result) {
00577         memcpy(result, source, size);
00578     }
00579     return result;
00580 }
00581 
00582 bool M2MBase::validate_string_length(const String &string, size_t min_length, size_t max_length)
00583 {
00584     bool valid = false;
00585 
00586     const size_t len = string.length();
00587     if ((len >= min_length) && (len <= max_length)) {
00588         valid = true;
00589     }
00590 
00591     return valid;
00592 }
00593 
00594 bool M2MBase::validate_string_length(const char* string, size_t min_length, size_t max_length)
00595 {
00596     bool valid = false;
00597 
00598     if (string != NULL) {
00599         const size_t len = strlen(string);
00600         if ((len >= min_length) && (len <= max_length)) {
00601             valid = true;
00602         }
00603     }
00604     return valid;
00605 }
00606 
00607 M2MReportHandler* M2MBase::create_report_handler()
00608 {
00609     if (!_report_handler) {
00610         _report_handler = new M2MReportHandler(*this);
00611     }
00612     return _report_handler;
00613 }
00614 
00615 M2MReportHandler* M2MBase::report_handler() const
00616 {
00617     return _report_handler;
00618 }
00619 
00620 void M2MBase::set_register_uri(bool register_uri)
00621 {
00622     _sn_resource->dynamic_resource_params->publish_uri = register_uri;
00623 }
00624 
00625 bool M2MBase::register_uri()
00626 {
00627     return _sn_resource->dynamic_resource_params->publish_uri;
00628 }
00629 
00630 bool M2MBase::is_integer(const String &value)
00631 {
00632     const char *s = value.c_str();
00633     if(value.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) {
00634         return false;
00635     }
00636     char * p;
00637     strtol(value.c_str(), &p, 10);
00638     return (*p == 0);
00639 }
00640 
00641 bool M2MBase::is_integer(const char *value)
00642 {
00643     assert(value != NULL);
00644 
00645     if((strlen(value) < 1) || ((!isdigit(value[0])) && (value[0] != '-') && (value[0] != '+'))) {
00646         return false;
00647     }
00648     char * p;
00649     strtol(value, &p, 10);
00650     return (*p == 0);
00651 }
00652 
00653 bool M2MBase::is_under_observation() const
00654 {
00655    bool under_observation = false;
00656     if(_report_handler) {
00657         under_observation = _report_handler->is_under_observation();
00658     }
00659     return under_observation;
00660 }
00661 
00662 bool M2MBase::set_value_updated_function(value_updated_callback callback)
00663 {
00664     value_updated_callback* old_callback = (value_updated_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00665     delete old_callback;
00666     // XXX: create a copy of the copy of callback object. Perhaps it would better to
00667     // give a reference as parameter and just store that, as it would save some memory.
00668     value_updated_callback* new_callback = new value_updated_callback(callback);
00669 
00670     return M2MCallbackStorage::add_callback(*this, new_callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00671 }
00672 
00673 bool M2MBase::set_value_updated_function(value_updated_callback2 callback)
00674 {
00675     M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00676 
00677     return M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00678 }
00679 
00680 bool M2MBase::is_value_updated_function_set() const
00681 {
00682     bool func_set = false;
00683     if ((M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback) == true) ||
00684         (M2MCallbackStorage::does_callback_exist(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2) == true)) {
00685 
00686         func_set = true;
00687     }
00688     return func_set;
00689 }
00690 
00691 void M2MBase::execute_value_updated(const String& name)
00692 {
00693     // Q: is there a point to call both callback types? Or should we call just one of them?
00694 
00695     value_updated_callback* callback = (value_updated_callback*)M2MCallbackStorage::get_callback(*this,
00696                                                                                                  M2MCallbackAssociation::M2MBaseValueUpdatedCallback);
00697     if (callback) {
00698         (*callback)(name.c_str());
00699     }
00700 
00701     value_updated_callback2 callback2 = (value_updated_callback2)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MBaseValueUpdatedCallback2);
00702     if (callback2) {
00703         (*callback2)(name.c_str());
00704     }
00705 }
00706 
00707 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE> &buffer, const char *s1, uint16_t i1, const char *s2, uint16_t i2)
00708 {
00709 
00710     if(!buffer.ensure_space(strlen(s1) + strlen(s2) + (MAX_INSTANCE_SIZE * 2) + 3 + 1)){
00711         return false;
00712     }
00713 
00714     buffer.append(s1);
00715     buffer.append('/');
00716     buffer.append_int(i1);
00717     buffer.append('/');
00718     buffer.append(s2);
00719     buffer.append('/');
00720     buffer.append_int(i2);
00721 
00722     return true;
00723 
00724 }
00725 
00726 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_2> &buffer, const char *s1, uint16_t i1, const char *s2)
00727 {
00728     if(!buffer.ensure_space(strlen(s1) + strlen(s2) + MAX_INSTANCE_SIZE + 2 + 1)){
00729         return false;
00730     }
00731 
00732     buffer.append(s1);
00733     buffer.append('/');
00734     buffer.append_int(i1);
00735     buffer.append('/');
00736     buffer.append(s2);
00737 
00738     return true;
00739 }
00740 
00741 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_3> &buffer, const char *s1, uint16_t i1, uint16_t i2)
00742 {
00743     if(!buffer.ensure_space(strlen(s1) + (MAX_INSTANCE_SIZE * 2) + 2 + 1)){
00744         return false;
00745     }
00746 
00747     buffer.append(s1);
00748     buffer.append('/');
00749     buffer.append_int(i1);
00750     buffer.append('/');
00751     buffer.append_int(i2);
00752 
00753     return true;
00754 }
00755 
00756 bool M2MBase::build_path(StringBuffer<MAX_PATH_SIZE_4> &buffer, const char *s1, uint16_t i1)
00757 {
00758     if(!buffer.ensure_space(strlen(s1) + MAX_INSTANCE_SIZE + 1 + 1)){
00759         return false;
00760     }
00761 
00762     buffer.append(s1);
00763     buffer.append('/');
00764     buffer.append_int(i1);
00765 
00766     return true;
00767 }
00768 
00769 char* M2MBase::stringdup(const char* src)
00770 {
00771     assert(src != NULL);
00772 
00773     const size_t len = strlen(src) + 1;
00774 
00775     char *dest = (char*)malloc(len);
00776 
00777     if (dest) {
00778         memcpy(dest, src, len);
00779     }
00780     return dest;
00781 }
00782 
00783 void M2MBase::free_resources()
00784 {
00785     // remove the nsdl structures from the nsdlinterface's lists.
00786     M2MObservationHandler *obs_handler = observation_handler();
00787     if (obs_handler) {
00788         tr_debug("M2MBase::free_resources()");
00789         obs_handler->resource_to_be_deleted(this);
00790     }
00791 
00792     if (_sn_resource->dynamic_resource_params->static_resource_parameters->free_on_delete) {
00793         sn_nsdl_static_resource_parameters_s *params =
00794                 const_cast<sn_nsdl_static_resource_parameters_s *>(_sn_resource->dynamic_resource_params->static_resource_parameters);
00795 
00796         free(params->path);
00797         //free(params->resource);
00798 #ifndef RESOURCE_ATTRIBUTES_LIST
00799 #ifndef DISABLE_RESOURCE_TYPE
00800         free(params->resource_type_ptr);
00801 #endif
00802 #ifndef DISABLE_INTERFACE_DESCRIPTION
00803         free(params->interface_description_ptr);
00804 #endif
00805 #else
00806         sn_nsdl_free_resource_attributes_list(_sn_resource->dynamic_resource_params->static_resource_parameters);
00807 #endif
00808         free(params);
00809     }
00810     if (_sn_resource->dynamic_resource_params->free_on_delete) {
00811         free(_sn_resource->dynamic_resource_params->resource);
00812         free(_sn_resource->dynamic_resource_params);
00813     }
00814 
00815     if(_sn_resource->free_on_delete && _sn_resource->identifier_int_type == false) {
00816         tr_debug("M2MBase::free_resources()");
00817         free(_sn_resource->identifier.name);
00818     }
00819     if(_sn_resource->free_on_delete) {
00820         free(_sn_resource);
00821     }
00822 }
00823 
00824 size_t M2MBase::resource_name_length() const
00825 {
00826     assert(_sn_resource->identifier_int_type == false);
00827     return strlen(_sn_resource->identifier.name);
00828 }
00829 
00830 sn_nsdl_dynamic_resource_parameters_s* M2MBase::get_nsdl_resource() const
00831 {
00832     return _sn_resource->dynamic_resource_params;
00833 }
00834 
00835 M2MBase::lwm2m_parameters_s* M2MBase::get_lwm2m_parameters() const
00836 {
00837     return _sn_resource;
00838 }
00839 
00840 uint16_t M2MBase::get_notification_msgid() const
00841 {
00842     return _sn_resource->dynamic_resource_params->msg_id;
00843 }
00844 
00845 void M2MBase::set_notification_msgid(uint16_t msgid)
00846 {
00847     _sn_resource->dynamic_resource_params->msg_id = msgid;
00848 }
00849 
00850 bool M2MBase::set_notification_delivery_status_cb(notification_delivery_status_cb callback, void *client_args)
00851 {
00852     M2MCallbackStorage::remove_callback(*this,
00853                                         M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
00854 
00855     return M2MCallbackStorage::add_callback(*this,
00856                                             (void*)callback,
00857                                             M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback,
00858                                             client_args);
00859 }
00860 
00861 void M2MBase::send_notification_delivery_status(const M2MBase& object, const NotificationDeliveryStatus status)
00862 {
00863     _sn_resource->dynamic_resource_params->notification_status = status;
00864     M2MCallbackAssociation* item = M2MCallbackStorage::get_association_item(object,
00865                                                                             M2MCallbackAssociation::M2MBaseNotificationDeliveryStatusCallback);
00866     if (item) {
00867         notification_delivery_status_cb callback = (notification_delivery_status_cb)item->_callback;
00868         if (callback) {
00869             (*callback)(object, status, item->_client_args);
00870         }
00871     }
00872 }
00873 
00874 NotificationDeliveryStatus M2MBase::get_notification_delivery_status() const
00875 {
00876     return _sn_resource->dynamic_resource_params->notification_status;
00877 }
00878 
00879 void M2MBase::clear_notification_delivery_status()
00880 {
00881     _sn_resource->dynamic_resource_params->notification_status = NOTIFICATION_STATUS_INIT;
00882 }