Timothy Beight / Mbed 2 deprecated 6_songs-from-the-cloud

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of 6_songs-from-the-cloud by MakingMusicWorkshop

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