Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-client by
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 }
Generated on Tue Jul 12 2022 18:06:59 by
1.7.2
