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