joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mnsdlinterface.cpp Source File

m2mnsdlinterface.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 // Note: this macro is needed on armcc to get the the PRI*32 macros
00018 // from inttypes.h in a C++ code.
00019 #ifndef __STDC_FORMAT_MACROS
00020 #define __STDC_FORMAT_MACROS
00021 #endif
00022 
00023 // Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX
00024 #ifndef __STDC_LIMIT_MACROS
00025 #define __STDC_LIMIT_MACROS
00026 #endif
00027 
00028 
00029 #include "include/nsdlaccesshelper.h"
00030 #include "include/m2mnsdlobserver.h"
00031 #include "include/m2mtlvdeserializer.h"
00032 #include "include/m2mtlvserializer.h"
00033 #include "include/m2mnsdlinterface.h"
00034 #include "mbed-client/m2mstring.h"
00035 #include "mbed-client/m2msecurity.h"
00036 #include "mbed-client/m2mserver.h"
00037 #include "mbed-client/m2mobject.h"
00038 #include "mbed-client/m2mobjectinstance.h"
00039 #include "mbed-client/m2mresource.h"
00040 #include "mbed-client/m2mconstants.h"
00041 #include "mbed-trace/mbed_trace.h"
00042 #include "mbed-client/m2mtimer.h"
00043 #include "source/libNsdl/src/include/sn_grs.h"
00044 
00045 #include <assert.h>
00046 #include <inttypes.h>
00047 
00048 #define BUFFER_SIZE 21
00049 #define TRACE_GROUP "mClt"
00050 
00051 M2MNsdlInterface::M2MNsdlInterface(M2MNsdlObserver &observer)
00052 : _observer(observer),
00053   _server(NULL),
00054   _security(NULL),
00055   _nsdl_exceution_timer(new M2MTimer(*this)),
00056   _registration_timer(new M2MTimer(*this)),
00057   _endpoint(NULL),
00058   _resource(NULL),
00059   _nsdl_handle(NULL),
00060   _counter_for_nsdl(0),
00061   _bootstrap_id(0),
00062   _register_ongoing(false),
00063   _unregister_ongoing(false),
00064   _update_register_ongoing(false)
00065 {
00066     tr_debug("M2MNsdlInterface::M2MNsdlInterface()");
00067     __nsdl_interface_list.push_back(this);
00068     _sn_nsdl_address.addr_len = 0;
00069     _sn_nsdl_address.addr_ptr = NULL;
00070     _sn_nsdl_address.port = 0;
00071 
00072     // This initializes libCoap and libNsdl
00073     // Parameters are function pointers to used memory allocation
00074     // and free functions in structure and used functions for sending
00075     // and receiving purposes.
00076     _nsdl_handle = sn_nsdl_init(&(__nsdl_c_send_to_server), &(__nsdl_c_received_from_server),
00077                  &(__nsdl_c_memory_alloc), &(__nsdl_c_memory_free));
00078 
00079 
00080     _server = new M2MServer();
00081     initialize();
00082 }
00083 
00084 M2MNsdlInterface::~M2MNsdlInterface()
00085 {
00086     tr_debug("M2MNsdlInterface::~M2MNsdlInterface() - IN");
00087     if(_resource) {
00088         memory_free(_resource->resource_parameters_ptr);
00089         memory_free(_resource);
00090     }
00091     if(_endpoint) {
00092          memory_free(_endpoint->endpoint_name_ptr);
00093          memory_free(_endpoint->lifetime_ptr);
00094          memory_free(_endpoint->location_ptr);
00095          memory_free(_endpoint);
00096     }
00097     delete _nsdl_exceution_timer;
00098     delete _registration_timer;
00099     _object_list.clear();
00100     delete _server;
00101     _security = NULL;
00102 
00103     sn_nsdl_destroy(_nsdl_handle);
00104     _nsdl_handle = NULL;
00105 
00106     M2MNsdlInterfaceList::const_iterator it;
00107     it = __nsdl_interface_list.begin();
00108     int index = 0;
00109     for (; it!=__nsdl_interface_list.end(); it++) {
00110         if ((*it) == this) {
00111             __nsdl_interface_list.erase(index);
00112             break;
00113         }
00114         index++;
00115     }
00116     tr_debug("M2MNsdlInterface::~M2MNsdlInterface() - OUT");
00117 }
00118 
00119 bool M2MNsdlInterface::initialize()
00120 {
00121     tr_debug("M2MNsdlInterface::initialize()");
00122     bool success = false;
00123 
00124     //Sets the packet retransmission attempts and time interval
00125     sn_nsdl_set_retransmission_parameters(_nsdl_handle,
00126                                           MBED_CLIENT_RECONNECTION_COUNT,
00127                                           MBED_CLIENT_RECONNECTION_INTERVAL);
00128 
00129     // We want to parse and handle bootstrap messages
00130     if (_nsdl_handle) {
00131         _nsdl_handle->handle_bootstrap_msg = false;
00132     }
00133 
00134     // Allocate the memory for resources
00135     _resource = (sn_nsdl_resource_info_s*)memory_alloc(sizeof(sn_nsdl_resource_info_s));
00136     if(_resource) {
00137         memset(_resource, 0, sizeof(sn_nsdl_resource_info_s));
00138         _resource->resource_parameters_ptr = (sn_nsdl_resource_parameters_s*)memory_alloc(sizeof(sn_nsdl_resource_parameters_s));
00139         if(_resource->resource_parameters_ptr) {
00140             memset(_resource->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s));
00141         }
00142     }
00143 
00144     //Allocate the memory for endpoint
00145     _endpoint = (sn_nsdl_ep_parameters_s*)memory_alloc(sizeof(sn_nsdl_ep_parameters_s));
00146     if(_endpoint) {
00147         memset(_endpoint, 0, sizeof(sn_nsdl_ep_parameters_s));
00148         success = true;
00149     }
00150     return success;
00151 }
00152 
00153 void M2MNsdlInterface::create_endpoint(const String &name,
00154                                        const String &type,
00155                                        const int32_t life_time,
00156                                        const String &domain,
00157                                        const uint8_t mode,
00158                                        const String &/*context_address*/)
00159 {
00160     tr_debug("M2MNsdlInterface::create_endpoint( name %s type %s lifetime %" PRId32 ", domain %s, mode %d)",
00161               name.c_str(), type.c_str(), life_time, domain.c_str(), mode);
00162     _endpoint_name = name;
00163     if(_endpoint){
00164         memset(_endpoint, 0, sizeof(sn_nsdl_ep_parameters_s));
00165         if(!_endpoint_name.empty()) {
00166             memory_free(_endpoint->endpoint_name_ptr);
00167             _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length());
00168             _endpoint->endpoint_name_len = _endpoint_name.length();
00169         }
00170         if(!type.empty()) {
00171             _endpoint->type_ptr = (uint8_t*)type.c_str();
00172             _endpoint->type_len =  type.length();
00173         }
00174         if(!domain.empty()) {
00175             _endpoint->domain_name_ptr = (uint8_t*)domain.c_str();
00176             _endpoint->domain_name_len = domain.length();
00177         }
00178         _endpoint->binding_and_mode = (sn_nsdl_oma_binding_and_mode_t)mode;
00179 
00180         // If lifetime is less than zero then leave the field empty
00181         if( life_time > 0) {
00182             set_endpoint_lifetime_buffer(life_time);
00183         }
00184     }
00185 }
00186 
00187 void M2MNsdlInterface::set_endpoint_lifetime_buffer(int lifetime)
00188 {
00189     // max len of "-9223372036854775808" plus zero termination
00190     char buffer[20+1];
00191 
00192     uint32_t size = m2m::itoa_c(lifetime, buffer);
00193 
00194     if (size <= sizeof(buffer)) {
00195         _endpoint->lifetime_ptr = alloc_string_copy((uint8_t*)buffer, size);
00196         if(_endpoint->lifetime_ptr) {
00197             _endpoint->lifetime_len =  size;
00198         } else {
00199             _endpoint->lifetime_len = 0;
00200         }
00201     }
00202 }
00203 
00204 
00205 void M2MNsdlInterface::delete_endpoint()
00206 {
00207     tr_debug("M2MNsdlInterface::delete_endpoint()");
00208     if(_endpoint) {
00209         free(_endpoint->lifetime_ptr);
00210 
00211         memory_free(_endpoint);
00212         _endpoint = NULL;
00213     }
00214 }
00215 
00216 bool M2MNsdlInterface::create_nsdl_list_structure(const M2MObjectList &object_list)
00217 {
00218     tr_debug("M2MNsdlInterface::create_nsdl_list_structure()");
00219     bool success = false;
00220     if(!object_list.empty()) {
00221        tr_debug("M2MNsdlInterface::create_nsdl_list_structure - Object count is %d", object_list.size());
00222         M2MObjectList::const_iterator it;
00223         it = object_list.begin();
00224         for ( ; it != object_list.end(); it++ ) {
00225             // Create NSDL structure for all Objects inside
00226             success = create_nsdl_object_structure(*it);
00227             add_object_to_list(*it);
00228         }
00229     }
00230     return success;
00231 }
00232 
00233 bool M2MNsdlInterface::delete_nsdl_resource(const String &resource_name)
00234 {
00235     tr_debug("M2MNsdlInterface::delete_nsdl_resource( %s)", resource_name.c_str());
00236     return (sn_nsdl_delete_resource(_nsdl_handle,
00237                                     resource_name.length(),
00238                                     (uint8_t *)resource_name.c_str()) == 0) ? true : false;
00239 }
00240 
00241 
00242 bool M2MNsdlInterface::create_bootstrap_resource(sn_nsdl_addr_s *address, const String &bootstrap_endpoint_name)
00243 {
00244 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00245     tr_debug("M2MNsdlInterface::create_bootstrap_resource()");
00246     bool success = false;
00247     sn_nsdl_bs_ep_info_t bootstrap_endpoint;
00248     tr_debug("M2MNsdlInterface::create_bootstrap_resource() - endpoint name: %s", bootstrap_endpoint_name.c_str());
00249     if (_endpoint->endpoint_name_ptr) {
00250         memory_free(_endpoint->endpoint_name_ptr);
00251     }
00252     //_endpoint->endpoint_name_ptr = (uint8_t*)bootstrap_endpoint_name.c_str();
00253     _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)bootstrap_endpoint_name.c_str(), bootstrap_endpoint_name.length());
00254     _endpoint->endpoint_name_len = bootstrap_endpoint_name.length();
00255     if(_bootstrap_id == 0) {
00256         _bootstrap_id = sn_nsdl_oma_bootstrap(_nsdl_handle,
00257                                                address,
00258                                                _endpoint,
00259                                                &bootstrap_endpoint);
00260         tr_debug("M2MNsdlInterface::create_bootstrap_resource - _bootstrap_id %d", _bootstrap_id);
00261         success = _bootstrap_id != 0;
00262 
00263     }
00264     return success;
00265 #else
00266     (void)address;
00267     (void)bootstrap_endpoint_name;
00268     return false;
00269 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00270 }
00271 
00272 bool M2MNsdlInterface::send_register_message(uint8_t* address,
00273                                              const uint16_t port,
00274                                              sn_nsdl_addr_type_e address_type)
00275 {
00276     tr_debug("M2MNsdlInterface::send_register_message()");
00277     _nsdl_exceution_timer->stop_timer();
00278     _nsdl_exceution_timer->start_timer(ONE_SECOND_TIMER * 1000,
00279                                        M2MTimerObserver::NsdlExecution,
00280                                        false);
00281     bool success = false;
00282     if(set_NSP_address(_nsdl_handle,address, port, address_type) == 0) {
00283         if(!_register_ongoing) {
00284             _register_ongoing = true;
00285             success = sn_nsdl_register_endpoint(_nsdl_handle,_endpoint) != 0;
00286         }
00287     }
00288     return success;
00289 }
00290 
00291 bool M2MNsdlInterface::send_update_registration(const uint32_t lifetime)
00292 {
00293     if (_update_register_ongoing) {
00294         tr_debug("M2MNsdlInterface::send_update_registration - update already in progress");
00295         return true;
00296     }
00297     tr_debug("M2MNsdlInterface::send_update_registration( lifetime %" PRIu32 ")", lifetime);
00298     bool success = false;
00299 
00300     create_nsdl_list_structure(_object_list);
00301     //If Lifetime value is 0, then don't change the existing lifetime value
00302     if(lifetime != 0) {
00303         if(_endpoint->lifetime_ptr) {
00304             memory_free(_endpoint->lifetime_ptr);
00305             _endpoint->lifetime_ptr = NULL;
00306             _endpoint->lifetime_len = 0;
00307         }
00308         set_endpoint_lifetime_buffer(lifetime);
00309 
00310         _registration_timer->stop_timer();
00311         _registration_timer->start_timer(registration_time() * 1000,
00312                                          M2MTimerObserver::Registration,
00313                                          false);
00314         if(_nsdl_handle &&
00315            _endpoint && _endpoint->lifetime_ptr) {
00316             tr_debug("M2MNsdlInterface::send_update_registration - new lifetime value");
00317             _update_register_ongoing = true;
00318             success = sn_nsdl_update_registration(_nsdl_handle,
00319                                                   _endpoint->lifetime_ptr,
00320                                                   _endpoint->lifetime_len) != 0;
00321         }
00322     } else {
00323         if(_nsdl_handle) {
00324             tr_debug("M2MNsdlInterface::send_update_registration - regular update");
00325             _update_register_ongoing = true;
00326             success = sn_nsdl_update_registration(_nsdl_handle, NULL, 0) != 0;
00327         }
00328     }
00329     return success;
00330 }
00331 
00332 bool M2MNsdlInterface::send_unregister_message()
00333 {
00334     tr_debug("M2MNsdlInterface::send_unregister_message");
00335     if (_unregister_ongoing) {
00336         tr_debug("M2MNsdlInterface::send_unregister_message - unregistration already in progress");
00337         return true;
00338     }
00339 
00340     bool success = false;
00341     _unregister_ongoing = true;
00342     success = sn_nsdl_unregister_endpoint(_nsdl_handle) != 0;
00343     return success;
00344 }
00345 
00346 // XXX: move these to common place, no need to copy these wrappers to multiple places:
00347 void *M2MNsdlInterface::memory_alloc(uint16_t size)
00348 {
00349     if(size)
00350         return malloc(size);
00351     else
00352         return 0;
00353 }
00354 
00355 void M2MNsdlInterface::memory_free(void *ptr)
00356 {
00357     if(ptr)
00358         free(ptr);
00359 }
00360 
00361 uint8_t* M2MNsdlInterface::alloc_string_copy(const uint8_t* source, uint16_t size)
00362 {
00363     assert(source != NULL);
00364 
00365     uint8_t* result = (uint8_t*)memory_alloc(size + 1);
00366     if (result) {
00367         memcpy(result, source, size);
00368         result[size] = '\0';
00369     }
00370     return result;
00371 }
00372 
00373 uint8_t M2MNsdlInterface::send_to_server_callback(struct nsdl_s * /*nsdl_handle*/,
00374                                                   sn_nsdl_capab_e /*protocol*/,
00375                                                   uint8_t *data_ptr,
00376                                                   uint16_t data_len,
00377                                                   sn_nsdl_addr_s *address)
00378 {
00379     tr_debug("M2MNsdlInterface::send_to_server_callback()");
00380     _observer.coap_message_ready(data_ptr,data_len,address);
00381     return 1;
00382 }
00383 
00384 uint8_t M2MNsdlInterface::received_from_server_callback(struct nsdl_s * nsdl_handle,
00385                                                         sn_coap_hdr_s *coap_header,
00386                                                         sn_nsdl_addr_s *address)
00387 {
00388     tr_debug("M2MNsdlInterface::received_from_server_callback - msg id:%" PRIu16, coap_header->msg_id);
00389     tr_debug("M2MNsdlInterface::received_from_server_callback - registration id:%" PRIu16, nsdl_handle->register_msg_id);
00390     tr_debug("M2MNsdlInterface::received_from_server_callback - unregistration id:%" PRIu16, nsdl_handle->unregister_msg_id);
00391     tr_debug("M2MNsdlInterface::received_from_server_callback - update registration id:%" PRIu16, nsdl_handle->update_register_msg_id);
00392     _observer.coap_data_processed();
00393     uint8_t value = 0;
00394     if(nsdl_handle && coap_header) {
00395         bool is_bootstrap_msg = address && (nsdl_handle->oma_bs_address_len == address->addr_len) &&
00396                                    (nsdl_handle->oma_bs_port == address->port) &&
00397                                    !memcmp(nsdl_handle->oma_bs_address_ptr, address->addr_ptr, nsdl_handle->oma_bs_address_len);
00398         if(coap_header->msg_id == nsdl_handle->register_msg_id) {
00399             _register_ongoing = false;
00400             if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CREATED) {
00401                 tr_debug("M2MNsdlInterface::received_from_server_callback - registration callback");
00402                 _observer.client_registered(_server);
00403                 // If lifetime is less than zero then leave the field empty
00404                 if(coap_header->options_list_ptr) {
00405                     if(coap_header->options_list_ptr->max_age_ptr) {
00406                         memory_free(_endpoint->lifetime_ptr);
00407                         _endpoint->lifetime_ptr = NULL;
00408                         _endpoint->lifetime_len = 0;
00409 
00410                         uint32_t max_time = 0;
00411                         for(int i=0;i < coap_header->options_list_ptr->max_age_len; i++) {
00412                             max_time += (*(coap_header->options_list_ptr->max_age_ptr + i) & 0xff) <<
00413                                      8*(coap_header->options_list_ptr->max_age_len- 1 - i);
00414                             }
00415                         // If lifetime is less than zero then leave the field empty
00416                         if( max_time > 0) {
00417                             set_endpoint_lifetime_buffer(max_time);
00418                         }
00419                     }
00420                     if(coap_header->options_list_ptr->location_path_ptr) {
00421 
00422                         memory_free(_endpoint->location_ptr);
00423 
00424                         _endpoint->location_ptr = alloc_string_copy(coap_header->options_list_ptr->location_path_ptr, coap_header->options_list_ptr->location_path_len);
00425                         if (_endpoint->location_ptr != NULL) {
00426                             _endpoint->location_len = coap_header->options_list_ptr->location_path_len;
00427                         }
00428                         sn_nsdl_set_endpoint_location(_nsdl_handle,_endpoint->location_ptr,_endpoint->location_len);
00429                     }
00430                 }
00431                 if(_endpoint->lifetime_ptr) {
00432                     _registration_timer->stop_timer();
00433                     _registration_timer->start_timer(registration_time() * 1000,
00434                                                      M2MTimerObserver::Registration,
00435                                                      false);
00436                 }
00437             } else {
00438                 tr_error("M2MNsdlInterface::received_from_server_callback - registration error %d", coap_header->msg_code);
00439                 // Try to do clean register again
00440                 if(COAP_MSG_CODE_RESPONSE_BAD_REQUEST == coap_header->msg_code ||
00441                    COAP_MSG_CODE_RESPONSE_FORBIDDEN == coap_header->msg_code) {
00442                     _observer.registration_error(M2MInterface::InvalidParameters, false);
00443                 } else {
00444                     _observer.registration_error(M2MInterface::NetworkError, true);
00445                 }
00446 
00447             }
00448         } else if(coap_header->msg_id == nsdl_handle->unregister_msg_id) {
00449             _unregister_ongoing = false;
00450             tr_debug("M2MNsdlInterface::received_from_server_callback - unregistration callback");
00451             if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_DELETED) {
00452                 _registration_timer->stop_timer();
00453                 _observer.client_unregistered();
00454             } else {
00455                 tr_error("M2MNsdlInterface::received_from_server_callback - unregistration error %d", coap_header->msg_code);
00456                 M2MInterface::Error error = interface_error(coap_header);
00457                 _observer.registration_error(error);
00458             }
00459         } else if(coap_header->msg_id == nsdl_handle->update_register_msg_id) {
00460             _update_register_ongoing = false;
00461             if(coap_header->msg_code == COAP_MSG_CODE_RESPONSE_CHANGED) {
00462                 tr_debug("M2MNsdlInterface::received_from_server_callback - registration_updated successfully");
00463                 _observer.registration_updated(*_server);
00464             } else {
00465                 tr_error("M2MNsdlInterface::received_from_server_callback - registration_updated failed %d", coap_header->msg_code);
00466                 _registration_timer->stop_timer();
00467                 _register_ongoing = true;
00468                 sn_nsdl_register_endpoint(_nsdl_handle,_endpoint);
00469             }
00470         }
00471 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00472         else if(coap_header->msg_id == nsdl_handle->bootstrap_msg_id) {
00473             tr_debug("M2MNsdlInterface::received_from_server_callback - bootstrap");
00474             _bootstrap_id = 0;
00475             M2MInterface::Error error = interface_error(coap_header);
00476             if(error != M2MInterface::ErrorNone) {
00477                 handle_bootstrap_error();
00478             }
00479         }
00480 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00481         else {
00482             if(COAP_MSG_CODE_REQUEST_PUT == coap_header->msg_code) {
00483                 if (is_bootstrap_msg) {
00484                     handle_bootstrap_put_message(coap_header, address);
00485                 }
00486             }
00487             else if(COAP_MSG_CODE_REQUEST_DELETE == coap_header->msg_code) {
00488                 if (is_bootstrap_msg) {
00489                     handle_bootstrap_delete(coap_header, address);
00490                 }
00491             }
00492             else if(COAP_MSG_CODE_REQUEST_POST == coap_header->msg_code) {
00493                 if(is_bootstrap_msg) {
00494                     handle_bootstrap_finished(coap_header, address);
00495                 }
00496                 else if(coap_header->uri_path_ptr) {
00497                     sn_coap_hdr_s *coap_response = NULL;
00498                     bool execute_value_updated = false;
00499                     M2MObjectInstance *obj_instance = NULL;
00500                     String resource_name = coap_to_string(coap_header->uri_path_ptr,
00501                                                           coap_header->uri_path_len);
00502 
00503                     String object_name;
00504                     int slash_found = resource_name.find_last_of('/');
00505                     //The POST operation here is only allowed for non-existing object instances
00506                     if(slash_found != -1) {
00507                         object_name = resource_name.substr(0,slash_found);
00508                         if( object_name.find_last_of('/') != -1){
00509                             coap_response = sn_nsdl_build_response(_nsdl_handle,
00510                                                                    coap_header,
00511                                                                    COAP_MSG_CODE_RESPONSE_NOT_FOUND);
00512                         } else {
00513                             int32_t instance_id = atoi(resource_name.substr(slash_found+1,
00514                                                      resource_name.size()-object_name.size()).c_str());
00515                             M2MBase* base = find_resource(object_name);
00516                             if(base && (instance_id >= 0) && (instance_id < UINT16_MAX)) {
00517                                 if(coap_header->payload_ptr) {
00518                                     M2MObject* object = static_cast<M2MObject*> (base);
00519                                     obj_instance = object->create_object_instance(instance_id);
00520                                     if(obj_instance) {
00521                                         obj_instance->set_operation(M2MBase::GET_PUT_POST_ALLOWED);
00522                                         coap_response = obj_instance->handle_post_request(_nsdl_handle,
00523                                                                                           coap_header,
00524                                                                                           this,
00525                                                                                           execute_value_updated);
00526                                     }
00527                                     if(coap_response && coap_response->msg_code != COAP_MSG_CODE_RESPONSE_CREATED) {
00528                                         //Invalid request so remove created ObjectInstance
00529                                         object->remove_object_instance(instance_id);
00530                                     } else  {
00531                                         tr_debug("M2MNsdlInterface::received_from_server_callback - Send Update registration for Create");
00532                                         send_update_registration();
00533                                     }
00534                                 } else {
00535                                     tr_debug("M2MNsdlInterface::received_from_server_callback - Missing Payload - Cannot create");
00536                                     coap_response = sn_nsdl_build_response(_nsdl_handle,
00537                                                                            coap_header,
00538                                                                            COAP_MSG_CODE_RESPONSE_BAD_REQUEST);
00539                                 }
00540                             } else { //if(base)
00541                                 tr_debug("M2MNsdlInterface::received_from_server_callback - Missing BASE - Cannot create");
00542                                 coap_response = sn_nsdl_build_response(_nsdl_handle,
00543                                                                        coap_header,
00544                                                                        COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED);
00545                             }
00546                         }
00547                     } else{ // if(slash_found != -1)
00548                         tr_debug("M2MNsdlInterface::received_from_server_callback - slash_found - Cannot create");
00549                         coap_response = sn_nsdl_build_response(_nsdl_handle,
00550                                                                coap_header,
00551                                                                COAP_MSG_CODE_RESPONSE_NOT_FOUND);
00552                     }
00553                     if(coap_response) {
00554                         tr_debug("M2MNsdlInterface::received_from_server_callback - send CoAP response");
00555                         (sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response) == 0) ? value = 0 : value = 1;
00556                         sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
00557                     }
00558                     if (execute_value_updated) {
00559                         value_updated(obj_instance, obj_instance->name());
00560                     }
00561                 }
00562             }
00563         }
00564     }
00565     return value;
00566 }
00567 
00568 uint8_t M2MNsdlInterface::resource_callback(struct nsdl_s */*nsdl_handle*/,
00569                                             sn_coap_hdr_s *received_coap_header,
00570                                             sn_nsdl_addr_s *address,
00571                                             sn_nsdl_capab_e /*nsdl_capab*/)
00572 {
00573     tr_debug("M2MNsdlInterface::resource_callback()");
00574     _observer.coap_data_processed();
00575     uint8_t result = 1;
00576     sn_coap_hdr_s *coap_response = NULL;
00577     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 4.00
00578     String resource_name = coap_to_string(received_coap_header->uri_path_ptr,
00579                                           received_coap_header->uri_path_len);
00580     tr_debug("M2MNsdlInterface::resource_callback() - resource_name %s", resource_name.c_str());
00581     bool execute_value_updated = false;
00582     M2MBase* base = find_resource(resource_name);
00583     if(base) {
00584         base->set_uri_path(resource_name);
00585         if(COAP_MSG_CODE_REQUEST_GET == received_coap_header->msg_code) {
00586             coap_response = base->handle_get_request(_nsdl_handle, received_coap_header,this);
00587         } else if(COAP_MSG_CODE_REQUEST_PUT == received_coap_header->msg_code) {
00588             coap_response = base->handle_put_request(_nsdl_handle, received_coap_header, this, execute_value_updated);
00589         } else if(COAP_MSG_CODE_REQUEST_POST == received_coap_header->msg_code) {
00590             if(base->base_type() == M2MBase::ResourceInstance) {
00591                 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00592             } else {
00593                 coap_response = base->handle_post_request(_nsdl_handle, received_coap_header,this, execute_value_updated);
00594             }
00595         } else if(COAP_MSG_CODE_REQUEST_DELETE == received_coap_header->msg_code) {
00596             // Delete the object instance
00597             tr_debug("M2MNsdlInterface::resource_callback() - DELETE the object instance");
00598             M2MBase::BaseType type = base->base_type();
00599             if(M2MBase::ObjectInstance == type) {
00600                 M2MBase* base_object = find_resource(base->name());
00601                 if(base_object) {
00602                     M2MObject *object = static_cast<M2MObject*> (base_object);
00603                     int slash_found = resource_name.find_last_of('/');
00604                     // Object instance validty checks done in upper level, no need for error handling
00605                     if(slash_found != -1) {
00606                         String object_name;
00607                         object_name = resource_name.substr(slash_found + 1, resource_name.length());
00608                         if (object->remove_object_instance(strtoul(
00609                                 object_name.c_str(),
00610                                 NULL,
00611                                 10))) {
00612                             msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
00613                         }
00614                     }
00615                 }
00616             } else {
00617                 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
00618             }
00619         } else if(COAP_MSG_TYPE_RESET == received_coap_header->msg_type) {
00620             // Cancel ongoing observation
00621             tr_error("M2MNsdlInterface::resource_callback() - RESET message");
00622             M2MBase::BaseType type = base->base_type();
00623             switch (type) {
00624                 case M2MBase::Object:
00625                     base->remove_observation_level(M2MBase::O_Attribute);
00626                     break;
00627                 case M2MBase::Resource:
00628                     base->remove_observation_level(M2MBase::R_Attribute);
00629                     break;
00630                 case M2MBase::ObjectInstance:
00631                     base->remove_observation_level(M2MBase::OI_Attribute);
00632                     break;
00633                 default:
00634                     break;
00635             }
00636             base->set_under_observation(false, this);
00637         }
00638     } else  {
00639         tr_debug("M2MNsdlInterface::resource_callback() - Resource NOT FOUND");
00640         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
00641     }
00642     if(!coap_response) {
00643             coap_response = sn_nsdl_build_response(_nsdl_handle,
00644                                                    received_coap_header,
00645                                                    msg_code);
00646     }
00647 
00648     if(coap_response) {
00649         tr_debug("M2MNsdlInterface::resource_callback() - send CoAP response");
00650         (sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response) == 0) ? result = 0 : result = 1;
00651         if(coap_response->payload_ptr) {
00652             free(coap_response->payload_ptr);
00653             coap_response->payload_ptr = NULL;
00654         }
00655         sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
00656     }
00657     if (execute_value_updated) {
00658         value_updated(base,base->uri_path());
00659     }
00660 
00661     return result;
00662 }
00663 
00664 bool M2MNsdlInterface::process_received_data(uint8_t *data,
00665                                              uint16_t data_size,
00666                                              sn_nsdl_addr_s *address)
00667 {
00668     tr_debug("M2MNsdlInterface::process_received_data( data size %d)", data_size);
00669     return (0 == sn_nsdl_process_coap(_nsdl_handle,
00670                                       data,
00671                                       data_size,
00672                                       address)) ? true : false;
00673 }
00674 
00675 void M2MNsdlInterface::stop_timers()
00676 {
00677     tr_debug("M2MNsdlInterface::stop_timers()");
00678     if(_registration_timer) {
00679         _registration_timer->stop_timer();
00680     }
00681     if (_nsdl_exceution_timer) {
00682         _nsdl_exceution_timer->stop_timer();
00683     }
00684     _bootstrap_id = 0;
00685     _register_ongoing = false;
00686     _unregister_ongoing = false;
00687     _update_register_ongoing = false;
00688 }
00689 
00690 void M2MNsdlInterface::timer_expired(M2MTimerObserver::Type type)
00691 {
00692     if(M2MTimerObserver::NsdlExecution == type) {
00693         sn_nsdl_exec(_nsdl_handle, _counter_for_nsdl);
00694         _counter_for_nsdl++;
00695     } else if(M2MTimerObserver::Registration == type) {
00696         tr_debug("M2MNsdlInterface::timer_expired - M2MTimerObserver::Registration - Send update registration");
00697         send_update_registration();
00698     }
00699 }
00700 
00701 void M2MNsdlInterface::observation_to_be_sent(M2MBase *object,
00702                                               uint16_t obs_number,
00703                                               m2m::Vector<uint16_t> changed_instance_ids,
00704                                               bool send_object)
00705 {
00706     __mutex_claim();
00707     tr_debug("M2MNsdlInterface::observation_to_be_sent(), %s", object->uri_path().c_str());
00708     if(object) {
00709         M2MBase::BaseType type = object->base_type();
00710         if(type == M2MBase::Object) {
00711             send_object_observation(static_cast<M2MObject*> (object),
00712                                     obs_number,
00713                                     changed_instance_ids,
00714                                     send_object);
00715         } else if(type == M2MBase::ObjectInstance) {
00716             send_object_instance_observation(static_cast<M2MObjectInstance*> (object), obs_number);
00717         } else if(type == M2MBase::Resource) {
00718             send_resource_observation(static_cast<M2MResource*> (object), obs_number);
00719         }
00720     }
00721     __mutex_release();
00722 }
00723 
00724 void M2MNsdlInterface::send_delayed_response(M2MBase *base)
00725 {
00726     __mutex_claim();
00727     tr_debug("M2MNsdlInterface::send_delayed_response()");
00728     M2MResource *resource = NULL;
00729     if(base) {
00730         if(M2MBase::Resource == base->base_type()) {
00731             resource = static_cast<M2MResource *> (base);
00732         }
00733         if(resource) {
00734             sn_coap_hdr_s * coap_response = static_cast<sn_coap_hdr_s *>(malloc(sizeof(sn_coap_hdr_s)));
00735             if(coap_response) {
00736                 memset(coap_response,0,sizeof(sn_coap_hdr_s));
00737 
00738                 coap_response->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
00739                 coap_response->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00740                 resource->get_delayed_token(coap_response->token_ptr,coap_response->token_len);
00741 
00742                 uint32_t length = 0;
00743                 resource->get_value(coap_response->payload_ptr, length);
00744                 coap_response->payload_len = length;
00745 
00746                 sn_nsdl_send_coap_message(_nsdl_handle, _nsdl_handle->nsp_address_ptr->omalw_address_ptr, coap_response);
00747 
00748                 if(coap_response->payload_ptr) {
00749                    free(coap_response->payload_ptr);
00750                    coap_response->payload_ptr = NULL;
00751                 }
00752                 if(coap_response->token_ptr) {
00753                     free(coap_response->token_ptr);
00754                     coap_response->token_ptr = NULL;
00755                 }
00756                 free(coap_response);
00757             }
00758         }
00759     }
00760     __mutex_release();
00761 }
00762 
00763 void M2MNsdlInterface::resource_to_be_deleted(const String &resource_name)
00764 {
00765     __mutex_claim();
00766     tr_debug("M2MNsdlInterface::resource_to_be_deleted(resource_name %s)", resource_name.c_str());
00767     delete_nsdl_resource(resource_name);
00768     __mutex_release();
00769 }
00770 
00771 void M2MNsdlInterface::value_updated(M2MBase *base,
00772                                      const String &object_name)
00773 {
00774     tr_debug("M2MNsdlInterface::value_updated()");
00775     if(base) {
00776         switch(base->base_type()) {
00777             case M2MBase::Object:
00778                 create_nsdl_object_structure(static_cast<M2MObject*> (base));
00779             break;
00780             case M2MBase::ObjectInstance:
00781                 create_nsdl_object_instance_structure(static_cast<M2MObjectInstance*> (base));
00782             break;
00783             case M2MBase::Resource: {
00784                     M2MResource* resource = static_cast<M2MResource*> (base);
00785                     create_nsdl_resource_structure(resource,object_name,
00786                                                resource->supports_multiple_instances());
00787             }
00788             break;
00789             case M2MBase::ResourceInstance: {
00790                 M2MResourceInstance* instance = static_cast<M2MResourceInstance*> (base);
00791                 create_nsdl_resource(instance,object_name);
00792             }
00793             break;
00794         }
00795     }
00796 
00797     if (base->is_value_updated_function_set()) {
00798         base->execute_value_updated(base->name());
00799     }
00800     else {
00801         _observer.value_updated(base);
00802     }
00803 }
00804 
00805 void M2MNsdlInterface::remove_object(M2MBase *object)
00806 {
00807     __mutex_claim();
00808     tr_debug("M2MNsdlInterface::remove_object()");
00809     M2MObject* rem_object = static_cast<M2MObject*> (object);
00810     if(rem_object && !_object_list.empty()) {
00811         M2MObjectList::const_iterator it;
00812         it = _object_list.begin();
00813         int index = 0;
00814         for ( ; it != _object_list.end(); it++, index++ ) {
00815             if((*it) == rem_object) {
00816                 _object_list.erase(index);
00817                 break;
00818             }
00819         }
00820     }
00821     if(_object_list.empty()) {
00822         _object_list.clear();
00823     }
00824     __mutex_release();
00825 }
00826 
00827 bool M2MNsdlInterface::create_nsdl_object_structure(M2MObject *object)
00828 {
00829     tr_debug("M2MNsdlInterface::create_nsdl_object_structure()");
00830     bool success = false;
00831     if(object) {
00832         M2MObjectInstanceList instance_list = object->instances();
00833         tr_debug("M2MNsdlInterface::create_nsdl_object_structure - Object Instance count %d", instance_list.size());
00834         if(!instance_list.empty()) {
00835            M2MObjectInstanceList::const_iterator it;
00836            it = instance_list.begin();
00837            for ( ; it != instance_list.end(); it++ ) {
00838                // Create NSDL structure for all object instances inside
00839                success = create_nsdl_object_instance_structure(*it);
00840            }
00841         }
00842     }
00843     if((object->operation() != M2MBase::NOT_ALLOWED)) {
00844         success = create_nsdl_resource(object,object->name(),object->register_uri());
00845     }
00846     return success;
00847 }
00848 
00849 bool M2MNsdlInterface::create_nsdl_object_instance_structure(M2MObjectInstance *object_instance)
00850 {
00851     tr_debug("M2MNsdlInterface::create_nsdl_object_instance_structure()");
00852     bool success = false;
00853     if( object_instance) {
00854 
00855         // Append object instance id to the object name.
00856         String object_name = object_instance->name();
00857         object_name.push_back('/');
00858         object_name.append_int(object_instance->instance_id());
00859 
00860         M2MResourceList res_list = object_instance->resources();
00861         tr_debug("M2MNsdlInterface::create_nsdl_object_instance_structure - ResourceBase count %d", res_list.size());
00862         if(!res_list.empty()) {
00863             M2MResourceList::const_iterator it;
00864             it = res_list.begin();
00865             for ( ; it != res_list.end(); it++ ) {
00866                 // Create NSDL structure for all resources inside
00867                 success = create_nsdl_resource_structure(*it,object_name,
00868                                                          (*it)->supports_multiple_instances());
00869             }
00870         }
00871         if(object_instance->operation() != M2MBase::NOT_ALLOWED) {
00872             success = create_nsdl_resource(object_instance,object_name,object_instance->register_uri());
00873         }
00874     }
00875     return success;
00876 }
00877 
00878 bool M2MNsdlInterface::create_nsdl_resource_structure(M2MResource *res,
00879                                                       const String &object_name,
00880                                                       bool multiple_instances)
00881 {
00882     tr_debug("M2MNsdlInterface::create_nsdl_resource_structure(object_name %s)", object_name.c_str());
00883     bool success = false;
00884     if(res) {
00885         // Append object name to the resource.
00886         // Take out the instance Id and append to the
00887         // resource name like "object/0/+ resource + / + 0"
00888         String res_name = object_name;
00889         if (strcmp(res_name.c_str(), res->uri_path().c_str()) != 0) {
00890             res_name.push_back('/');
00891             res_name.append(res->name().c_str(),res->name().length());
00892         }
00893 
00894         // if there are multiple instances supported
00895         // then add instance Id into creating resource path
00896         // else normal /object_id/object_instance/resource_id format.
00897         if(multiple_instances) {
00898             M2MResourceInstanceList res_list = res->resource_instances();
00899             tr_debug("M2MNsdlInterface::create_nsdl_resource_structure - ResourceInstance count %d", res_list.size());
00900             if(!res_list.empty()) {
00901                 M2MResourceInstanceList::const_iterator it;
00902                 it = res_list.begin();
00903                 for ( ; it != res_list.end(); it++ ) {
00904                     String inst_name = res_name;
00905                     // Create NSDL structure for all resources inside
00906                     inst_name.push_back('/');
00907                     inst_name.append_int((*it)->instance_id());
00908 
00909                     success = create_nsdl_resource((*it),inst_name,(*it)->register_uri());
00910                 }
00911                 // Register the main Resource as well along with ResourceInstances
00912                 success = create_nsdl_resource(res,res_name,res->register_uri());
00913             }
00914         } else {
00915             tr_debug("M2MNsdlInterface::create_nsdl_resource_structure - res_name %s", res_name.c_str());
00916             success = create_nsdl_resource(res,res_name,res->register_uri());
00917         }
00918     }
00919     return success;
00920 }
00921 
00922 bool M2MNsdlInterface::create_nsdl_resource(M2MBase *base, const String &name, bool publish_uri)
00923 {
00924     __mutex_claim();
00925     tr_debug("M2MNsdlInterface::create_nsdl_resource(name %s)", name.c_str());
00926     bool success = false;
00927     uint8_t* buffer = 0;
00928     uint32_t length = 0;
00929 
00930     // Create the NSDL Resource Pointer...
00931     if(base) {
00932         sn_nsdl_resource_info_s* resource = sn_nsdl_get_resource(_nsdl_handle,
00933                                                                  name.length(),
00934                                                                  (uint8_t*)name.c_str());
00935 
00936         if(resource) {
00937             bool changed = false;
00938             success = true;
00939             if(resource->mode == SN_GRS_STATIC) {
00940                 if((M2MBase::Resource == base->base_type() ||
00941                    M2MBase::ResourceInstance == base->base_type()) &&
00942                    M2MBase::Static == base->mode()) {
00943                     M2MResourceInstance *res = (M2MResourceInstance*) base;
00944                     res->get_value(buffer,length);
00945                     if(resource->resource) {
00946                         memory_free(resource->resource);
00947                     }
00948                     resource->resource = buffer;
00949                     resource->resourcelen = length;
00950                     resource->publish_uri = publish_uri;
00951                 }
00952             }
00953             // Check if the access level for the resource has changed.
00954             if(resource->access != (sn_grs_resource_acl_e)base->operation()) {
00955                 changed = true;
00956                 resource->access = (sn_grs_resource_acl_e)base->operation();
00957             }
00958             if(resource->resource_parameters_ptr) {
00959                 // Check if the observation parameter for the resource has changed.
00960                 if(resource->resource_parameters_ptr->observable != (uint8_t)base->is_observable()) {
00961                     changed = true;
00962                     resource->resource_parameters_ptr->observable = (uint8_t)base->is_observable();
00963                 }
00964             }
00965             if(changed && resource->resource_parameters_ptr) {
00966                 resource->resource_parameters_ptr->registered = SN_NDSL_RESOURCE_NOT_REGISTERED;
00967             }
00968         } else if(_resource) {
00969             base->set_under_observation(false,this);
00970             //TODO: implement access control
00971             // Currently complete access is given
00972             _resource->access = (sn_grs_resource_acl_e)base->operation();
00973 
00974             if((M2MBase::Resource == base->base_type() ||
00975                 M2MBase::ResourceInstance == base->base_type()) &&
00976                M2MBase::Static == base->mode()) {
00977                 M2MResourceInstance *res = (M2MResourceInstance*)base;
00978                 // Static resource is updated
00979                 _resource->mode = SN_GRS_STATIC;
00980 
00981                 res->get_value(buffer,length);
00982                 _resource->resource = buffer;
00983                 _resource->resourcelen = length;
00984             }
00985 
00986             if(M2MBase::Dynamic == base->mode()){
00987               // Dynamic resource is updated
00988                _resource->mode = SN_GRS_DYNAMIC;
00989                _resource->sn_grs_dyn_res_callback = __nsdl_c_callback;
00990             }
00991 
00992             if( _resource->path != NULL ){
00993                 memory_free(_resource->path);
00994                 _resource->path = NULL;
00995             }
00996             if(name.length() > 0 ){
00997                 _resource->path = alloc_string_copy((uint8_t*)name.c_str(), name.length());
00998                 if(_resource->path) {
00999                     _resource->pathlen = name.length();
01000                 }
01001             }
01002             if(!base->resource_type().empty() && _resource->resource_parameters_ptr) {
01003                 _resource->resource_parameters_ptr->resource_type_ptr =
01004                     alloc_string_copy((uint8_t*)base->resource_type().c_str(),
01005                           base->resource_type().length());
01006                 if(_resource->resource_parameters_ptr->resource_type_ptr) {
01007                     _resource->resource_parameters_ptr->resource_type_len =
01008                            base->resource_type().length();
01009                 }
01010             }
01011             if(!base->interface_description().empty() && _resource->resource_parameters_ptr) {
01012                 _resource->resource_parameters_ptr->interface_description_ptr =
01013                     alloc_string_copy((uint8_t*)base->interface_description().c_str(),
01014                           base->interface_description().length());
01015                 if(_resource->resource_parameters_ptr->interface_description_ptr) {
01016                     _resource->resource_parameters_ptr->interface_description_len =
01017                            base->interface_description().length();
01018                  }
01019             }
01020             if(_resource->resource_parameters_ptr) {
01021                 _resource->resource_parameters_ptr->coap_content_type = base->coap_content_type();
01022                 _resource->resource_parameters_ptr->observable = (uint8_t)base->is_observable();
01023             }
01024             _resource->publish_uri = publish_uri;
01025             int8_t result = sn_nsdl_create_resource(_nsdl_handle,_resource);
01026             tr_debug("M2MNsdlInterface::create_nsdl_resource - Creating in NSDL-C result %d", result);
01027 
01028             // Either the resource is created or it already
01029             // exists , then result is success.
01030             if (result == 0 ||
01031                result == -2){
01032                 success = true;
01033             }
01034 
01035             if(_resource->path) {
01036                 memory_free(_resource->path);
01037             }
01038             if(_resource->resource_parameters_ptr->resource_type_ptr){
01039                 memory_free(_resource->resource_parameters_ptr->resource_type_ptr);
01040             }
01041             if(_resource->resource_parameters_ptr->interface_description_ptr){
01042                 memory_free(_resource->resource_parameters_ptr->interface_description_ptr);
01043             }
01044             if (_resource->resource) {
01045                 memory_free(_resource->resource);
01046             }
01047 
01048             //Clear up the filled resource to fill up new resource.
01049             clear_resource(_resource);
01050 
01051             if(success) {
01052                base->set_under_observation(false,this);
01053             }
01054         }
01055     }
01056     __mutex_release();
01057     return success;
01058 }
01059 
01060 // convenience method to get the URI from its buffer field...
01061 String M2MNsdlInterface::coap_to_string(uint8_t *coap_data,int coap_data_length)
01062 {
01063     String value = "";
01064     if (coap_data != NULL && coap_data_length > 0) {
01065         value.append_raw((char *)coap_data,coap_data_length);
01066     }
01067     return value;
01068 }
01069 
01070 uint64_t M2MNsdlInterface::registration_time()
01071 {
01072     uint64_t value = 0;
01073     if(_endpoint->lifetime_ptr) {
01074         value = atol((const char*)_endpoint->lifetime_ptr);
01075     }
01076 
01077     if(value >= OPTIMUM_LIFETIME) {
01078         value = value - REDUCE_LIFETIME;
01079     } else {
01080         value = REDUCTION_FACTOR * value;
01081     }
01082     tr_debug("M2MNsdlInterface::registration_time - value (in seconds) %ld", value);
01083     return value;
01084 }
01085 
01086 M2MBase* M2MNsdlInterface::find_resource(const String &object_name)
01087 {
01088     M2MBase *object = NULL;
01089     if(!_object_list.empty()) {
01090         M2MObjectList::const_iterator it;
01091         it = _object_list.begin();
01092         for ( ; it != _object_list.end(); it++ ) {
01093             if((*it)->name() == object_name) {
01094                 object = (*it);
01095                 tr_debug("M2MNsdlInterface::find_resource(%s) found", object_name.c_str());
01096                 break;
01097             }
01098             object = find_resource((*it),object_name);
01099             if(object != NULL) {
01100                 tr_debug("M2MNsdlInterface::find_resource(%s) found", object_name.c_str());
01101                 break;
01102             }
01103         }
01104     }
01105     return object;
01106 }
01107 
01108 M2MBase* M2MNsdlInterface::find_resource(const M2MObject *object,
01109                                          const String &object_instance)
01110 {
01111     M2MBase *instance = NULL;
01112     if(object) {
01113         M2MObjectInstanceList list = object->instances();
01114         if(!list.empty()) {
01115             M2MObjectInstanceList::const_iterator it;
01116             it = list.begin();
01117             for ( ; it != list.end(); it++ ) {
01118                 // Append object instance id to the object name.
01119                 String name = (*it)->name();
01120                 name.push_back('/');
01121                 name.append_int((*it)->instance_id());
01122 
01123                 if(name == object_instance){
01124                     instance = (*it);
01125                     break;
01126                 }
01127                 instance = find_resource((*it),object_instance);
01128                 if(instance != NULL){
01129                     break;
01130                 }
01131             }
01132         }
01133     }
01134     return instance;
01135 }
01136 
01137 M2MBase* M2MNsdlInterface::find_resource(const M2MObjectInstance *object_instance,
01138                                          const String &resource_instance)
01139 {
01140     M2MBase *instance = NULL;
01141     if(object_instance) {
01142         M2MResourceList list = object_instance->resources();
01143         if(!list.empty()) {
01144             M2MResourceList::const_iterator it;
01145             it = list.begin();
01146             for ( ; it != list.end(); it++ ) {
01147                 String name = object_instance->name();
01148                 // Append object instance id to the object name.
01149                 name.push_back('/');
01150                 name.append_int(object_instance->instance_id());
01151 
01152                 name.push_back('/');
01153                 name+= (*it)->name();
01154 
01155                 if(name == resource_instance) {
01156                     instance = *it;
01157                     break;
01158                 } else if((*it)->supports_multiple_instances()) {
01159                     instance = find_resource((*it),name, resource_instance);
01160                     if(instance != NULL){
01161                         break;
01162                     }
01163                 }
01164             }
01165         }
01166     }
01167     return instance;
01168 }
01169 
01170 M2MBase* M2MNsdlInterface::find_resource(const M2MResource *resource,
01171                                          const String &object_name,
01172                                          const String &resource_instance)
01173 {
01174     M2MBase *res = NULL;
01175     if(resource) {
01176         if(resource->supports_multiple_instances()) {
01177             M2MResourceInstanceList list = resource->resource_instances();
01178             if(!list.empty()) {
01179                 M2MResourceInstanceList::const_iterator it;
01180                 it = list.begin();
01181                 for ( ; it != list.end(); it++ ) {
01182                     String name = object_name;
01183                     // if there are multiple instances supported
01184                     // then add instance Id into creating resource path
01185                     // else normal /object_id/object_instance/resource_id format.
01186 
01187                     name.push_back('/');
01188                     name.append_int((*it)->instance_id());
01189 
01190                     if(name == resource_instance){
01191                         res = (*it);
01192                         break;
01193                     }
01194                 }
01195             }
01196         }
01197     }
01198     return res;
01199 }
01200 
01201 bool M2MNsdlInterface::object_present(M2MObject* object) const
01202 {
01203     bool success = false;
01204     if(object && !_object_list.empty()) {
01205         M2MObjectList::const_iterator it;
01206         it = _object_list.begin();
01207         for ( ; it != _object_list.end(); it++ ) {
01208             if((*it) == object) {
01209                 success = true;
01210                 break;
01211             }
01212         }
01213     }
01214     return success;
01215 }
01216 
01217 bool M2MNsdlInterface::add_object_to_list(M2MObject* object)
01218 {
01219     bool success = false;
01220     if(object && !object_present(object)) {
01221         _object_list.push_back(object);
01222         success = true;
01223     }
01224     return success;
01225 }
01226 
01227 void M2MNsdlInterface::clear_resource(sn_nsdl_resource_info_s *&resource)
01228 {
01229     //Clear up the filled resource to fill up new resource.
01230     if(resource && resource->resource_parameters_ptr) {
01231         sn_nsdl_resource_parameters_s *temp_resource_parameter = resource->resource_parameters_ptr;
01232         memset(resource->resource_parameters_ptr, 0, sizeof(sn_nsdl_resource_parameters_s));
01233         memset(resource,0, sizeof(sn_nsdl_resource_info_s));
01234         resource->resource_parameters_ptr = temp_resource_parameter;
01235     }
01236 }
01237 
01238 M2MInterface::Error M2MNsdlInterface::interface_error(sn_coap_hdr_s *coap_header)
01239 {
01240     M2MInterface::Error error = M2MInterface::ErrorNone;
01241     if(coap_header) {
01242         switch(coap_header->msg_code) {
01243             case COAP_MSG_CODE_RESPONSE_BAD_REQUEST:
01244             case COAP_MSG_CODE_RESPONSE_BAD_OPTION:
01245             case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_INCOMPLETE:
01246             case COAP_MSG_CODE_RESPONSE_PRECONDITION_FAILED:
01247             case COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE:
01248             case COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT:
01249                 error = M2MInterface::InvalidParameters;
01250                 break;
01251             case COAP_MSG_CODE_RESPONSE_UNAUTHORIZED:
01252             case COAP_MSG_CODE_RESPONSE_FORBIDDEN:
01253             case COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE:
01254             case COAP_MSG_CODE_RESPONSE_NOT_FOUND:
01255             case COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED:
01256                 error = M2MInterface::NotAllowed;
01257                 break;
01258             case COAP_MSG_CODE_RESPONSE_CREATED:
01259             case COAP_MSG_CODE_RESPONSE_DELETED:
01260             case COAP_MSG_CODE_RESPONSE_VALID:
01261             case COAP_MSG_CODE_RESPONSE_CHANGED:
01262             case COAP_MSG_CODE_RESPONSE_CONTENT:
01263                 error = M2MInterface::ErrorNone;
01264                 break;
01265             default:
01266                 error = M2MInterface::UnknownError;
01267                 break;
01268         }
01269         if(coap_header->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED) {
01270             error = M2MInterface::NetworkError;
01271         }
01272     }
01273     return error;
01274 }
01275 
01276 void M2MNsdlInterface::send_object_observation(M2MObject *object,
01277                                                uint16_t obs_number,
01278                                                m2m::Vector<uint16_t> changed_instance_ids,
01279                                                bool send_object)
01280 {
01281     tr_debug("M2MNsdlInterface::send_object_observation");
01282     if(object) {
01283         uint8_t *value = 0;
01284         uint32_t length = 0;
01285         uint8_t *token = 0;
01286         uint32_t token_length = 0;
01287 
01288         M2MTLVSerializer serializer;
01289         // Send whole object structure
01290         if (send_object) {
01291             value = serializer.serialize(object->instances(), length);
01292         }
01293         // Send only changed object instances
01294         else {
01295             M2MObjectInstanceList list;
01296             Vector<uint16_t>::const_iterator it;
01297             it = changed_instance_ids.begin();
01298             for (; it != changed_instance_ids.end(); it++){
01299                 M2MObjectInstance* obj_instance = object->object_instance(*it);
01300                 if (obj_instance){
01301                     list.push_back(obj_instance);
01302                 }
01303             }
01304             if (!list.empty()) {
01305                 value = serializer.serialize(list, length);
01306                 list.clear();
01307             }
01308         }
01309 
01310         object->get_observation_token(token,token_length);
01311 
01312         send_notification(token,
01313                           token_length,
01314                           value,
01315                           length,
01316                           obs_number,
01317                           object->max_age(),
01318                           object->coap_content_type(),
01319                           object->uri_path());
01320 
01321         memory_free(value);
01322         memory_free(token);
01323     }
01324 }
01325 
01326 void M2MNsdlInterface::send_object_instance_observation(M2MObjectInstance *object_instance,
01327                                                         uint16_t obs_number)
01328 {
01329     tr_debug("M2MNsdlInterface::send_object_instance_observation");
01330     if(object_instance) {
01331         uint8_t *value = 0;
01332         uint32_t length = 0;
01333         uint8_t *token = 0;
01334         uint32_t token_length = 0;
01335 
01336         M2MTLVSerializer serializer;
01337         value = serializer.serialize(object_instance->resources(), length);
01338 
01339         object_instance->get_observation_token(token,token_length);
01340 
01341         send_notification(token,
01342                           token_length,
01343                           value,
01344                           length,
01345                           obs_number,
01346                           object_instance->max_age(),
01347                           object_instance->coap_content_type(),
01348                           object_instance->uri_path());
01349 
01350         memory_free(value);
01351         memory_free(token);
01352     }
01353 }
01354 
01355 void M2MNsdlInterface::send_resource_observation(M2MResource *resource,
01356                                                  uint16_t obs_number)
01357 {
01358     tr_debug("M2MNsdlInterface::send_resource_observation");
01359     if(resource) {
01360         uint8_t *value = 0;
01361         uint32_t length = 0;
01362         uint8_t *token = 0;
01363         uint32_t token_length = 0;
01364 
01365         resource->get_observation_token(token,token_length);
01366         uint8_t content_type = 0;
01367         if(M2MResourceInstance::OPAQUE == resource->resource_instance_type()) {
01368             content_type = COAP_CONTENT_OMA_OPAQUE_TYPE;
01369         }
01370         if (resource->resource_instance_count() > 0) {
01371             content_type = COAP_CONTENT_OMA_TLV_TYPE;
01372             M2MTLVSerializer serializer;
01373             value = serializer.serialize(resource, length);
01374         } else {
01375             resource->get_value(value,length);
01376         }
01377         send_notification(token,
01378                           token_length,
01379                           value,
01380                           length,
01381                           obs_number,
01382                           resource->max_age(),
01383                           content_type,
01384                           resource->uri_path());
01385 
01386         memory_free(value);
01387         memory_free(token);
01388     }
01389 }
01390 
01391 void M2MNsdlInterface::build_observation_number(uint8_t *obs_number,
01392                                                 uint8_t *obs_len,
01393                                                 uint16_t number)
01394 {
01395     if(number > 0xFF) {
01396         *obs_len = 2;
01397         *(obs_number) = (number >> 8) & 0x00FF;
01398         obs_number[1] = number & 0x00FF;
01399     } else {
01400         *obs_len = 1;
01401         *(obs_number) = number & 0x00FF;
01402     }
01403 }
01404 
01405 void M2MNsdlInterface::send_notification(uint8_t *token,
01406                                          uint8_t  token_length,
01407                                          uint8_t *value,
01408                                          uint32_t value_length,
01409                                          uint16_t observation,
01410                                          uint32_t max_age,
01411                                          uint8_t  coap_content_type,
01412                                          const String  &uri_path)
01413 
01414 {
01415     tr_debug("M2MNsdlInterface::send_notification");
01416     sn_coap_hdr_s *notification_message_ptr;
01417 
01418     /* Allocate and initialize memory for header struct */
01419     notification_message_ptr = static_cast<sn_coap_hdr_s *>(memory_alloc(sizeof(sn_coap_hdr_s)));
01420     if (notification_message_ptr) {
01421         memset(notification_message_ptr, 0, sizeof(sn_coap_hdr_s));
01422 
01423         notification_message_ptr->options_list_ptr = (sn_coap_options_list_s *)memory_alloc(sizeof(sn_coap_options_list_s));
01424         if (notification_message_ptr->options_list_ptr) {
01425 
01426             memset(notification_message_ptr->options_list_ptr , 0, sizeof(sn_coap_options_list_s));
01427 
01428             /* Fill header */
01429             notification_message_ptr->msg_type = COAP_MSG_TYPE_CONFIRMABLE;
01430             notification_message_ptr->msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
01431 
01432             /* Fill token */
01433             notification_message_ptr->token_len = token_length;
01434             notification_message_ptr->token_ptr = token;
01435 
01436             /* Fill payload */
01437             notification_message_ptr->payload_len = value_length;
01438             notification_message_ptr->payload_ptr = value;
01439 
01440             /* Fill uri path */
01441             notification_message_ptr->uri_path_len = uri_path.size();
01442             notification_message_ptr->uri_path_ptr = (uint8_t *)uri_path.c_str();
01443 
01444             /* Fill observe */
01445             uint8_t observation_number[2];
01446             uint8_t observation_number_length = 0;
01447 
01448             build_observation_number(observation_number,
01449                                      &observation_number_length,
01450                                      observation);
01451             notification_message_ptr->options_list_ptr->observe_len = observation_number_length;
01452             notification_message_ptr->options_list_ptr->observe_ptr = observation_number;
01453 
01454             notification_message_ptr->options_list_ptr->max_age_ptr =
01455                     m2m::String::convert_integer_to_array(max_age,
01456                                                           notification_message_ptr->options_list_ptr->max_age_len);
01457 
01458             notification_message_ptr->content_type_ptr =
01459                     m2m::String::convert_integer_to_array(coap_content_type,
01460                                                           notification_message_ptr->content_type_len);
01461 
01462             /* Send message */
01463             sn_nsdl_send_coap_message(_nsdl_handle,
01464                                       _nsdl_handle->nsp_address_ptr->omalw_address_ptr,
01465                                       notification_message_ptr);
01466 
01467             /* Free memory */
01468             notification_message_ptr->uri_path_ptr = NULL;
01469             notification_message_ptr->payload_ptr = NULL;
01470             notification_message_ptr->options_list_ptr->observe_ptr = NULL;
01471             notification_message_ptr->token_ptr = NULL;
01472             if (notification_message_ptr->content_type_ptr) {
01473                 free(notification_message_ptr->content_type_ptr);
01474             }
01475             notification_message_ptr->content_type_ptr = NULL;
01476             if (notification_message_ptr->options_list_ptr->max_age_ptr) {
01477                 free(notification_message_ptr->options_list_ptr->max_age_ptr);
01478             }
01479             notification_message_ptr->options_list_ptr->max_age_ptr = NULL;
01480         }
01481         sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, notification_message_ptr);
01482     }
01483 }
01484 
01485 nsdl_s * M2MNsdlInterface::get_nsdl_handle()
01486 {
01487     return _nsdl_handle;
01488 }
01489 
01490 void M2MNsdlInterface::handle_bootstrap_put_message(sn_coap_hdr_s *coap_header,
01491                                                 sn_nsdl_addr_s *address) {
01492 #ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01493     tr_debug("M2MNsdlInterface::handle_bootstrap_message");
01494     uint8_t response_code = COAP_MSG_CODE_RESPONSE_CHANGED;
01495     sn_coap_hdr_s *coap_response = NULL;
01496     bool success = false;
01497     bool security_object = false;
01498     uint16_t content_type = 0;
01499 
01500     if (!_security) {
01501         _security = new M2MSecurity(M2MSecurity::M2MServer);
01502     }
01503 
01504     String resource_name = coap_to_string(coap_header->uri_path_ptr,
01505                                           coap_header->uri_path_len);
01506     tr_debug("M2MNsdlInterface::handle_bootstrap_message - uri %s", resource_name.c_str());
01507 
01508     // Check incoming object
01509     if (resource_name.compare(0,1,"0") == 0) {
01510         security_object = true;
01511         if(_security) {
01512             success = true;
01513             // Not mandatory resource that's why it must be created first
01514             _security->create_resource(M2MSecurity::ShortServerID, 1);
01515             // Change operation mode
01516             M2MResourceList list = _security->object_instance()->resources();
01517             if(!list.empty()) {
01518                 M2MResourceList::const_iterator it;
01519                 it = list.begin();
01520                 for ( ; it != list.end(); it++ ) {
01521                     (*it)->set_operation(M2MBase::PUT_ALLOWED);
01522                 }
01523             }
01524         }
01525     }
01526     else if (resource_name.compare(0,1,"1") == 0) {
01527         success = true;
01528     }
01529 
01530     if (success) {
01531         // Send delayed response if token is part of the message
01532         if (coap_header->token_ptr) {
01533             tr_debug("M2MNsdlInterface::handle_bootstrap_message - send delayed response");
01534             coap_response = sn_nsdl_build_response(_nsdl_handle,
01535                                                    coap_header,
01536                                                    COAP_MSG_CODE_EMPTY);
01537             if (coap_response) {
01538                 coap_response->msg_type = COAP_MSG_TYPE_ACKNOWLEDGEMENT;
01539                 sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
01540                 sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
01541             }
01542         }
01543 
01544         if(coap_header->content_type_ptr) {
01545             content_type = String::convert_array_to_integer(coap_header->content_type_ptr,
01546                                                             coap_header->content_type_len);
01547         }
01548 
01549         tr_debug("M2MNsdlInterface::handle_bootstrap_message - content_type %d", content_type);
01550         if (content_type != COAP_CONTENT_OMA_TLV_TYPE) {
01551             success = false;
01552         }
01553         if (success) {
01554             success = parse_bootstrap_message(coap_header, security_object);
01555             // Set operation back to default ones
01556             if (_security) {
01557                 M2MResourceList list = _security->object_instance()->resources();
01558                 if(!list.empty()) {
01559                     M2MResourceList::const_iterator it;
01560                     it = list.begin();
01561                     for ( ; it != list.end(); it++ ) {
01562                         (*it)->set_operation(M2MBase::NOT_ALLOWED);
01563                     }
01564                 }
01565             }
01566         }
01567     }
01568 
01569     if (!success) {
01570         response_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
01571         handle_bootstrap_error();
01572     }
01573     coap_response = sn_nsdl_build_response(_nsdl_handle,
01574                                            coap_header,
01575                                            response_code);
01576     if (coap_response) {
01577         sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
01578         sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
01579     }
01580 #else
01581     (void) coap_header;
01582     (void) address;
01583 #endif
01584 }
01585 
01586 bool M2MNsdlInterface::parse_bootstrap_message(sn_coap_hdr_s *coap_header, bool is_security_object)
01587 {
01588 #ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01589     tr_debug("M2MNsdlInterface::parse_bootstrap_put_message");
01590     M2MTLVDeserializer *deserializer = new M2MTLVDeserializer();
01591     bool ret = false;
01592     bool is_obj_instance = false;
01593     uint16_t instance_id = 0;
01594     if (deserializer && _security) {
01595         ret = is_obj_instance = deserializer->is_object_instance(coap_header->payload_ptr);
01596         if (!is_obj_instance) {
01597             ret = deserializer->is_resource(coap_header->payload_ptr);
01598         }
01599 
01600         if (ret) {
01601             M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
01602             if (is_obj_instance) {
01603                 if (is_security_object) {
01604                     error = deserializer->deserialise_object_instances(coap_header->payload_ptr,
01605                                                                coap_header->payload_len,
01606                                                                *_security,
01607                                                                M2MTLVDeserializer::Put);
01608                     }
01609                 else {
01610                     error = deserializer->deserialise_object_instances(coap_header->payload_ptr,
01611                                                                coap_header->payload_len,
01612                                                                *_server,
01613                                                                M2MTLVDeserializer::Put);
01614                 }
01615             }
01616             else {
01617                 if (is_security_object) {
01618                     instance_id = deserializer->instance_id(coap_header->payload_ptr);
01619                     error = deserializer->deserialize_resources(coap_header->payload_ptr,
01620                                                                coap_header->payload_len,
01621                                                                *_security->object_instance(instance_id),
01622                                                                M2MTLVDeserializer::Put);
01623                 }
01624                 else {
01625                     instance_id = deserializer->instance_id(coap_header->payload_ptr);
01626                     error = deserializer->deserialize_resources(coap_header->payload_ptr,
01627                                                                coap_header->payload_len,
01628                                                                *_server->object_instance(instance_id),
01629                                                                M2MTLVDeserializer::Post);
01630                 }
01631             }
01632 
01633             if (error != M2MTLVDeserializer::None) {
01634                 tr_error("M2MNsdlInterface::parse_bootstrap_put_message - error %d", error);
01635                 ret = false;
01636             }
01637         }
01638     }
01639     delete deserializer;
01640     return ret;
01641 #else
01642     (void) coap_header;
01643     (void) is_security_object;
01644     return false;
01645 #endif
01646 }
01647 
01648 void M2MNsdlInterface::handle_bootstrap_finished(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address)
01649 {
01650 #ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01651     String object_name = coap_to_string(coap_header->uri_path_ptr,
01652                                           coap_header->uri_path_len);
01653     tr_debug("M2MNsdlInterface::handle_bootstrap_finished - path: %s", object_name.c_str());
01654     sn_coap_hdr_s *coap_response = NULL;
01655     uint8_t msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
01656 
01657     // Accept only '/bs' path and check that needed data is in security object
01658     if (object_name.size() != 2 ||
01659             object_name.compare(0,2,BOOTSTRAP_URI) != 0 ||
01660             !validate_security_object()) {
01661         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
01662     } else {
01663         // Add short server id to server object
01664         _server->set_resource_value(M2MServer::ShortServerID,
01665                                     _security->resource_value_int(M2MSecurity::ShortServerID));
01666     }
01667 
01668     coap_response = sn_nsdl_build_response(_nsdl_handle,
01669                                            coap_header,
01670                                            msg_code);
01671     if(coap_response) {
01672         sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
01673         sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
01674     }
01675     if (COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) {
01676         // Switch back to original ep name
01677         if (_endpoint->endpoint_name_ptr) {
01678             memory_free(_endpoint->endpoint_name_ptr);
01679         }
01680         _endpoint->endpoint_name_ptr = alloc_string_copy((uint8_t*)_endpoint_name.c_str(), _endpoint_name.length());
01681         _endpoint->endpoint_name_len = _endpoint_name.length();
01682         _observer.bootstrap_done(_security);
01683     } else {
01684         handle_bootstrap_error();
01685     }
01686 #else
01687     (void) coap_header;
01688     (void) address;
01689 #endif
01690 }
01691 
01692 void M2MNsdlInterface::handle_bootstrap_delete(sn_coap_hdr_s *coap_header,sn_nsdl_addr_s *address)
01693 {
01694 #ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01695     sn_coap_hdr_s *coap_response = NULL;
01696     uint8_t msg_code = COAP_MSG_CODE_RESPONSE_DELETED;
01697     String object_name = coap_to_string(coap_header->uri_path_ptr,
01698                                           coap_header->uri_path_len);
01699     tr_debug("M2MNsdlInterface::handle_bootstrap_delete - obj %s", object_name.c_str());
01700 
01701     // Only following paths are accepted, 0, 0/0
01702     if (object_name.size() == 2 || object_name.size() > 3) {
01703         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
01704     }
01705     else if ((object_name.size() == 1 && object_name.compare(0,1,"0") != 0) ||
01706             (object_name.size() == 3 && object_name.compare(0,3,"0/0") != 0)) {
01707         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
01708     }
01709 
01710     coap_response = sn_nsdl_build_response(_nsdl_handle,
01711                                            coap_header,
01712                                            msg_code);
01713 
01714     if(coap_response) {
01715         sn_nsdl_send_coap_message(_nsdl_handle, address, coap_response);
01716         sn_nsdl_release_allocated_coap_msg_mem(_nsdl_handle, coap_response);
01717         if(_security) {
01718             _security->clear_resources();
01719         }
01720     } else {
01721         handle_bootstrap_error();
01722     }
01723 #else
01724     (void) coap_header;
01725     (void) address;
01726 #endif
01727 }
01728 
01729 bool M2MNsdlInterface::validate_security_object()
01730 {
01731 #ifndef M2M_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01732     tr_debug("M2MNsdlInterface::validate_security_object");
01733     if (_security) {
01734         String address = _security->resource_value_string(M2MSecurity::M2MServerUri);
01735         uint32_t sec_mode = _security->resource_value_int(M2MSecurity::SecurityMode);
01736         bool is_bs_server = _security->resource_value_int(M2MSecurity::BootstrapServer);
01737         uint32_t public_key_size = _security->get_resource(M2MSecurity::PublicKey)->value_length();
01738         uint32_t server_key_size = _security->get_resource(M2MSecurity::ServerPublicKey)->value_length();
01739         uint32_t pkey_size = _security->get_resource(M2MSecurity::Secretkey)->value_length();
01740         tr_debug("M2MNsdlInterface::validate_security_object - Server URI /0/0: %s", address.c_str());
01741         tr_debug("M2MNsdlInterface::validate_security_object - is bs server /0/1: %d", is_bs_server);
01742         tr_debug("M2MNsdlInterface::validate_security_object - Security Mode /0/2: %d", sec_mode);
01743         tr_debug("M2MNsdlInterface::validate_security_object - Public key size /0/3: %d", public_key_size);
01744         tr_debug("M2MNsdlInterface::validate_security_object - Server Public key size /0/4: %d", server_key_size);
01745         tr_debug("M2MNsdlInterface::validate_security_object - Secret key size /0/5: %d", pkey_size);
01746         // Only NoSec and Certificate modes are supported
01747         if (!address.empty() && !is_bs_server) {
01748             if (M2MSecurity::Certificate == sec_mode) {
01749                 if (!public_key_size || !server_key_size || !pkey_size) {
01750                     return false;
01751                 } else {
01752                     return true;
01753                 }
01754             } else if (M2MSecurity::NoSecurity == sec_mode){
01755                 return true;
01756             } else {
01757                 return false;
01758             }
01759         } else {
01760             return false;
01761         }
01762     }
01763     return false;
01764 #else
01765     return false;
01766 #endif
01767 }
01768 
01769 void M2MNsdlInterface::handle_bootstrap_error()
01770 {
01771     tr_debug("M2MNsdlInterface::handle_bootstrap_error()");
01772     if (_security) {
01773         delete _security;
01774         _security = NULL;
01775     }
01776     _observer.bootstrap_error();
01777 }
01778 
01779 const String& M2MNsdlInterface::endpoint_name() const
01780 {
01781     return _endpoint_name;
01782 }