sandbox / mbed-client

Fork of mbed-client by Christopher Haster

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