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.
m2mresourcebase.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 // Needed for PRIu64 on FreeRTOS 00018 #include <stdio.h> 00019 // Note: this macro is needed on armcc to get the the limit macros like UINT16_MAX 00020 #ifndef __STDC_LIMIT_MACROS 00021 #define __STDC_LIMIT_MACROS 00022 #endif 00023 00024 // Note: this macro is needed on armcc to get the the PRI*32 macros 00025 // from inttypes.h in a C++ code. 00026 #ifndef __STDC_FORMAT_MACROS 00027 #define __STDC_FORMAT_MACROS 00028 #endif 00029 00030 #include <stdlib.h> 00031 #include "mbed-client/m2mresourcebase.h" 00032 #include "mbed-client/m2mconstants.h" 00033 #include "mbed-client/m2mobservationhandler.h" 00034 #include "mbed-client/m2mobject.h" 00035 #include "mbed-client/m2mobjectinstance.h" 00036 #include "include/m2mcallbackstorage.h" 00037 #include "include/m2mreporthandler.h" 00038 #include "include/nsdllinker.h" 00039 #include "include/m2mtlvserializer.h" 00040 #include "mbed-client/m2mblockmessage.h" 00041 #include "mbed-trace/mbed_trace.h" 00042 00043 #define TRACE_GROUP "mClt" 00044 00045 M2MResourceBase::M2MResourceBase( 00046 const String &res_name, 00047 M2MBase::Mode resource_mode, 00048 const String &resource_type, 00049 M2MBase::DataType type, 00050 char* path, 00051 bool external_blockwise_store, 00052 bool multiple_instance) 00053 : M2MBase(res_name, 00054 resource_mode, 00055 #ifndef DISABLE_RESOURCE_TYPE 00056 resource_type, 00057 #endif 00058 path, 00059 external_blockwise_store, 00060 multiple_instance, 00061 type) 00062 #ifndef DISABLE_BLOCK_MESSAGE 00063 ,_block_message_data(NULL), 00064 #endif 00065 _notification_status(M2MResourceBase::INIT) 00066 { 00067 } 00068 00069 M2MResourceBase::M2MResourceBase( 00070 const String &res_name, 00071 M2MBase::Mode resource_mode, 00072 const String &resource_type, 00073 M2MBase::DataType type, 00074 const uint8_t *value, 00075 const uint8_t value_length, 00076 char* path, 00077 bool external_blockwise_store, 00078 bool multiple_instance) 00079 : M2MBase(res_name, 00080 resource_mode, 00081 #ifndef DISABLE_RESOURCE_TYPE 00082 resource_type, 00083 #endif 00084 path, 00085 external_blockwise_store, 00086 multiple_instance, 00087 type) 00088 #ifndef DISABLE_BLOCK_MESSAGE 00089 ,_block_message_data(NULL), 00090 #endif 00091 _notification_status(M2MResourceBase::INIT) 00092 { 00093 M2MBase::set_base_type(M2MBase::ResourceInstance); 00094 if( value != NULL && value_length > 0 ) { 00095 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00096 res->resource = alloc_string_copy(value, value_length); 00097 res->resourcelen = value_length; 00098 } 00099 } 00100 00101 M2MResourceBase::M2MResourceBase( 00102 const lwm2m_parameters_s* s, 00103 M2MBase::DataType /*type*/) 00104 : M2MBase(s) 00105 #ifndef DISABLE_BLOCK_MESSAGE 00106 ,_block_message_data(NULL), 00107 #endif 00108 _notification_status(M2MResourceBase::INIT) 00109 { 00110 // we are not there yet for this check as this is called from M2MResource(): assert(base_type() == M2MBase::ResourceInstance); 00111 } 00112 00113 M2MResourceBase::~M2MResourceBase() 00114 { 00115 execute_callback* callback = (execute_callback*)M2MCallbackStorage::remove_callback(*this, 00116 M2MCallbackAssociation::M2MResourceInstanceExecuteCallback); 00117 delete callback; 00118 00119 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2); 00120 #ifndef DISABLE_BLOCK_MESSAGE 00121 incoming_block_message_callback *in_callback = (incoming_block_message_callback*)M2MCallbackStorage::remove_callback(*this, 00122 M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback); 00123 delete in_callback; 00124 00125 outgoing_block_message_callback *out_callback = (outgoing_block_message_callback*)M2MCallbackStorage::remove_callback(*this, 00126 M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback); 00127 delete out_callback; 00128 #endif 00129 00130 notification_sent_callback *notif_callback = (notification_sent_callback*)M2MCallbackStorage::remove_callback(*this, 00131 M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback); 00132 delete notif_callback; 00133 00134 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2); 00135 00136 notification_status_callback *notif_status_callback = (notification_status_callback*)M2MCallbackStorage::remove_callback(*this, 00137 M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback); 00138 delete notif_status_callback; 00139 00140 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2); 00141 00142 #ifndef DISABLE_BLOCK_MESSAGE 00143 delete _block_message_data; 00144 #endif 00145 } 00146 00147 M2MResourceBase::ResourceType M2MResourceBase::resource_instance_type() const 00148 { 00149 M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters(); 00150 M2MBase::DataType type = param->data_type; 00151 return convert_data_type(type); 00152 } 00153 00154 00155 bool M2MResourceBase::set_execute_function(execute_callback callback) 00156 { 00157 execute_callback* old_callback = (execute_callback*)M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback); 00158 delete old_callback; 00159 // XXX: create a copy of the copy of callback object. Perhaps it would better to 00160 // give a reference as parameter and just store that, as it would save some memory. 00161 execute_callback* new_callback = new execute_callback(callback); 00162 00163 return M2MCallbackStorage::add_callback(*this, new_callback, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback); 00164 } 00165 00166 bool M2MResourceBase::set_execute_function(execute_callback_2 callback) 00167 { 00168 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2); 00169 00170 return M2MCallbackStorage::add_callback(*this, (void*)callback, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2); 00171 } 00172 00173 void M2MResourceBase::clear_value() 00174 { 00175 tr_debug("M2MResourceBase::clear_value"); 00176 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00177 free(res->resource); 00178 res->resource = NULL; 00179 res->resourcelen = 0; 00180 00181 report(); 00182 } 00183 00184 bool M2MResourceBase::set_value(int64_t value) 00185 { 00186 bool success; 00187 // max len of "-9223372036854775808" plus zero termination 00188 char buffer[20+1]; 00189 uint32_t size = m2m::itoa_c(value, buffer); 00190 00191 success = set_value((const uint8_t*)buffer, size); 00192 00193 return success; 00194 } 00195 00196 bool M2MResourceBase::set_value(const uint8_t *value, 00197 const uint32_t value_length) 00198 { 00199 tr_debug("M2MResourceBase::set_value()"); 00200 bool success = false; 00201 bool changed = has_value_changed(value,value_length); 00202 if( value != NULL && value_length > 0 ) { 00203 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00204 free(res->resource); 00205 res->resource = NULL; 00206 res->resourcelen = 0; 00207 res->resource = alloc_string_copy(value, value_length); 00208 if(res->resource) { 00209 success = true; 00210 res->resourcelen = value_length; 00211 if (changed) { 00212 report_value_change(); 00213 } 00214 } 00215 } 00216 return success; 00217 } 00218 00219 bool M2MResourceBase::set_value_raw(uint8_t *value, 00220 const uint32_t value_length) 00221 00222 { 00223 tr_debug("M2MResourceBase::set_value_raw()"); 00224 bool success = false; 00225 bool changed = has_value_changed(value,value_length); 00226 if( value != NULL && value_length > 0 ) { 00227 success = true; 00228 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00229 free(res->resource); 00230 res->resource = value; 00231 res->resourcelen = value_length; 00232 if (changed) { 00233 report_value_change(); 00234 } 00235 } 00236 return success; 00237 } 00238 00239 void M2MResourceBase::report() 00240 { 00241 M2MBase::Observation observation_level = M2MBase::observation_level(); 00242 tr_debug("M2MResourceBase::report() - level %d", observation_level); 00243 00244 // We must combine the parent object/objectinstance/resource observation information 00245 // when determining if there is observation set or not. 00246 M2MObjectInstance& object_instance = get_parent_resource().get_parent_object_instance(); 00247 int parent_observation_level = (int)object_instance.observation_level(); 00248 00249 parent_observation_level |= (int)object_instance.get_parent_object().observation_level(); 00250 parent_observation_level |= (int)get_parent_resource().observation_level(); 00251 parent_observation_level |= (int)observation_level; 00252 00253 tr_debug("M2MResourceBase::report() - combined level %d", parent_observation_level); 00254 00255 if((M2MBase::O_Attribute & parent_observation_level) == M2MBase::O_Attribute || 00256 (M2MBase::OI_Attribute & parent_observation_level) == M2MBase::OI_Attribute) { 00257 tr_debug("M2MResourceBase::report() -- object/instance level"); 00258 M2MObjectInstance& object_instance = get_parent_resource().get_parent_object_instance(); 00259 object_instance.notification_update((M2MBase::Observation)parent_observation_level); 00260 } 00261 00262 if(M2MBase::Dynamic == mode() && 00263 (M2MBase::R_Attribute & parent_observation_level) == M2MBase::R_Attribute) { 00264 tr_debug("M2MResourceBase::report() - resource level"); 00265 00266 if (((resource_instance_type() != M2MResourceBase::STRING) && 00267 (resource_instance_type() != M2MResourceBase::OPAQUE)) && 00268 (observation_level != M2MBase::None)) { 00269 M2MReportHandler *report_handler = M2MBase::report_handler(); 00270 if (report_handler && is_observable()) { 00271 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00272 if(res->resource) { 00273 report_handler->set_value(atof((const char*)res->resource)); 00274 } else { 00275 report_handler->set_value(0); 00276 } 00277 } 00278 } 00279 else { 00280 if (base_type() == M2MBase::ResourceInstance) { 00281 const M2MResource& parent_resource = get_parent_resource(); 00282 M2MReportHandler *report_handler = parent_resource.report_handler(); 00283 if(report_handler && parent_resource.is_observable()) { 00284 report_handler->set_notification_trigger(parent_resource.get_parent_object_instance().instance_id()); 00285 } 00286 } 00287 } 00288 } else if(M2MBase::Static == mode()) { 00289 M2MObservationHandler *obs_handler = observation_handler(); 00290 if(obs_handler) { 00291 obs_handler->value_updated(this); 00292 } 00293 } else { 00294 if (is_observable()) { 00295 tr_warn("M2MResourceBase::report() - resource %s is observable but not yet subscribed!", uri_path()); 00296 } 00297 tr_debug("M2MResourceBase::report() - mode = %d, is_observable = %d", mode(), is_observable()); 00298 } 00299 } 00300 00301 bool M2MResourceBase::has_value_changed(const uint8_t* value, const uint32_t value_len) 00302 { 00303 bool changed = false; 00304 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00305 00306 if(value_len != res->resourcelen) { 00307 changed = true; 00308 } else if(value && !res->resource) { 00309 changed = true; 00310 } else if(res->resource && !value) { 00311 changed = true; 00312 } else { 00313 if (res->resource) { 00314 if (memcmp(value, res->resource, res->resourcelen) != 0) { 00315 changed = true; 00316 } 00317 } 00318 } 00319 return changed; 00320 } 00321 00322 void M2MResourceBase::report_value_change() 00323 { 00324 if (resource_instance_type() == M2MResourceBase::STRING || 00325 resource_instance_type() == M2MResourceBase::OPAQUE) { 00326 M2MReportHandler *report_handler = M2MBase::report_handler(); 00327 if(report_handler && is_under_observation()) { 00328 report_handler->set_notification_trigger(); 00329 } 00330 } 00331 report(); 00332 } 00333 00334 void M2MResourceBase::execute(void *arguments) 00335 { 00336 // XXX: this line is expected by seven testcases and until this code hits master branch 00337 // the testcases can not be modified and we need to print the false information too. 00338 tr_debug("M2MResourceBase::execute"); 00339 00340 execute_callback* callback = (execute_callback*)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback); 00341 00342 if (callback) { 00343 (*callback)(arguments); 00344 } 00345 00346 execute_callback_2 callback2 = (execute_callback_2)M2MCallbackStorage::get_callback(*this, M2MCallbackAssociation::M2MResourceInstanceExecuteCallback2); 00347 if (callback2) { 00348 (*callback2)(arguments); 00349 } 00350 } 00351 00352 void M2MResourceBase::get_value(uint8_t *&value, uint32_t &value_length) 00353 { 00354 value_length = 0; 00355 if(value) { 00356 free(value); 00357 value = NULL; 00358 } 00359 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource(); 00360 if(res->resource && res->resourcelen > 0) { 00361 value = alloc_string_copy(res->resource, res->resourcelen); 00362 if(value) { 00363 value_length = res->resourcelen; 00364 } 00365 } 00366 } 00367 00368 int64_t M2MResourceBase::get_value_int() const 00369 { 00370 int64_t value_int = 0; 00371 00372 // XXX: this relies on having a zero terminated value?! 00373 const char *value_string = (char *)value(); 00374 if (value_string) { 00375 value_int = atoll(value_string); 00376 } 00377 return value_int; 00378 } 00379 00380 String M2MResourceBase::get_value_string() const 00381 { 00382 // XXX: do a better constructor to avoid pointless malloc 00383 String value; 00384 if (get_nsdl_resource()->resource) { 00385 value.append_raw((char*)get_nsdl_resource()->resource, get_nsdl_resource()->resourcelen); 00386 } 00387 return value; 00388 } 00389 00390 uint8_t* M2MResourceBase::value() const 00391 { 00392 return get_nsdl_resource()->resource; 00393 } 00394 00395 uint32_t M2MResourceBase::value_length() const 00396 { 00397 return get_nsdl_resource()->resourcelen; 00398 } 00399 00400 sn_coap_hdr_s* M2MResourceBase::handle_get_request(nsdl_s *nsdl, 00401 sn_coap_hdr_s *received_coap_header, 00402 M2MObservationHandler *observation_handler) 00403 { 00404 tr_info("M2MResourceBase::handle_get_request()"); 00405 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT; 00406 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, 00407 received_coap_header, 00408 msg_code); 00409 if(received_coap_header) { 00410 // process the GET if we have registered a callback for it 00411 if ((operation() & SN_GRS_GET_ALLOWED) != 0) { 00412 if(coap_response) { 00413 bool content_type_present = false; 00414 if(received_coap_header->options_list_ptr && 00415 received_coap_header->options_list_ptr->accept != COAP_CT_NONE) { 00416 content_type_present = true; 00417 coap_response->content_format = received_coap_header->options_list_ptr->accept; 00418 } 00419 if(!content_type_present) { 00420 if(resource_instance_type() == M2MResourceInstance::OPAQUE) { 00421 coap_response->content_format = sn_coap_content_format_e(COAP_CONTENT_OMA_OPAQUE_TYPE); 00422 } else { 00423 coap_response->content_format = sn_coap_content_format_e(COAP_CONTENT_OMA_PLAIN_TEXT_TYPE); 00424 } 00425 } 00426 // fill in the CoAP response payload 00427 coap_response->payload_ptr = NULL; 00428 uint32_t payload_len = 0; 00429 #ifndef DISABLE_BLOCK_MESSAGE 00430 //If handler exists it means that resource value is stored in application side 00431 if (block_message() && block_message()->is_block_message()) { 00432 outgoing_block_message_callback* outgoing_block_message_cb = (outgoing_block_message_callback*)M2MCallbackStorage::get_callback(*this, 00433 M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback); 00434 if (outgoing_block_message_cb) { 00435 String name = ""; 00436 if (received_coap_header->uri_path_ptr != NULL && 00437 received_coap_header->uri_path_len > 0) { 00438 name.append_raw((char *)received_coap_header->uri_path_ptr, 00439 received_coap_header->uri_path_len); 00440 } 00441 (*outgoing_block_message_cb)(name, coap_response->payload_ptr, payload_len); 00442 } 00443 } else { 00444 #endif 00445 if (coap_response->content_format == COAP_CONTENT_OMA_TLV_TYPE || 00446 coap_response->content_format == COAP_CONTENT_OMA_TLV_TYPE_OLD) { 00447 set_coap_content_type(coap_response->content_format); 00448 coap_response->payload_ptr = M2MTLVSerializer::serialize(&get_parent_resource(), payload_len); 00449 } else { 00450 get_value(coap_response->payload_ptr,payload_len); 00451 } 00452 #ifndef DISABLE_BLOCK_MESSAGE 00453 } 00454 #endif 00455 tr_debug("M2MResourceBase::handle_get_request() - Request Content-type: %d", coap_response->content_format); 00456 coap_response->payload_len = payload_len; 00457 coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response); 00458 if (coap_response->options_list_ptr) { 00459 coap_response->options_list_ptr->max_age = max_age(); 00460 } 00461 00462 if(received_coap_header->options_list_ptr) { 00463 if(received_coap_header->options_list_ptr->observe != -1) { 00464 if (is_observable()) { 00465 uint32_t number = 0; 00466 uint8_t observe_option = 0; 00467 observe_option = received_coap_header->options_list_ptr->observe; 00468 00469 if(START_OBSERVATION == observe_option) { 00470 // If the observe length is 0 means register for observation. 00471 if(received_coap_header->options_list_ptr->observe != -1) { 00472 number = received_coap_header->options_list_ptr->observe; 00473 } 00474 00475 // If the observe value is 0 means register for observation. 00476 if(number == 0) { 00477 tr_info("M2MResourceBase::handle_get_request - put resource under observation"); 00478 set_under_observation(true,observation_handler); 00479 send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED); 00480 M2MBase::add_observation_level(M2MBase::R_Attribute); 00481 if (coap_response->options_list_ptr) { 00482 coap_response->options_list_ptr->observe = observation_number(); 00483 } 00484 } 00485 00486 if(received_coap_header->token_ptr) { 00487 set_observation_token(received_coap_header->token_ptr, 00488 received_coap_header->token_len); 00489 } 00490 00491 } else if (STOP_OBSERVATION == observe_option) { 00492 tr_info("M2MResourceBase::handle_get_request - stops observation"); 00493 set_under_observation(false,NULL); 00494 M2MBase::remove_observation_level(M2MBase::R_Attribute); 00495 send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED); 00496 } 00497 } else { 00498 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00499 } 00500 } 00501 } 00502 } 00503 }else { 00504 tr_error("M2MResourceBase::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00505 // Operation is not allowed. 00506 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00507 } 00508 } else { 00509 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00510 } 00511 if(coap_response) { 00512 coap_response->msg_code = msg_code; 00513 } 00514 return coap_response; 00515 } 00516 00517 sn_coap_hdr_s* M2MResourceBase::handle_put_request(nsdl_s *nsdl, 00518 sn_coap_hdr_s *received_coap_header, 00519 M2MObservationHandler *observation_handler, 00520 bool &execute_value_updated) 00521 { 00522 tr_info("M2MResourceBase::handle_put_request()"); 00523 00524 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04 00525 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl, 00526 received_coap_header, 00527 msg_code); 00528 // process the PUT if we have registered a callback for it 00529 if(received_coap_header && coap_response) { 00530 uint16_t coap_content_type = 0; 00531 if(received_coap_header->content_format != COAP_CT_NONE) { 00532 coap_content_type = received_coap_header->content_format; 00533 } 00534 if(received_coap_header->options_list_ptr && 00535 received_coap_header->options_list_ptr->uri_query_ptr) { 00536 char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr, 00537 received_coap_header->options_list_ptr->uri_query_len); 00538 if (query){ 00539 tr_info("M2MResourceBase::handle_put_request() - query %s", query); 00540 00541 // if anything was updated, re-initialize the stored notification attributes 00542 if (!handle_observation_attribute(query)){ 00543 tr_error("M2MResourceBase::handle_put_request() - Invalid query"); 00544 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; 00545 } 00546 free(query); 00547 } 00548 else { 00549 // memory allocation for query fails 00550 tr_error("M2MResourceBase::handle_put_request() - Out of memory !!!"); 00551 msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; // 4.00 00552 } 00553 } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) { 00554 tr_debug("M2MResourceBase::handle_put_request() - Request Content-type: %d", coap_content_type); 00555 00556 if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type || 00557 COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) { 00558 msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; 00559 } else { 00560 #ifndef DISABLE_BLOCK_MESSAGE 00561 if (block_message()) { 00562 block_message()->set_message_info(received_coap_header); 00563 if (block_message()->is_block_message()) { 00564 incoming_block_message_callback* incoming_block_message_cb = (incoming_block_message_callback*)M2MCallbackStorage::get_callback(*this, 00565 M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback); 00566 if (incoming_block_message_cb) { 00567 (*incoming_block_message_cb)(_block_message_data); 00568 } 00569 if (block_message()->is_last_block()) { 00570 block_message()->clear_values(); 00571 coap_response->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED; 00572 } else { 00573 coap_response->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING; 00574 } 00575 if (block_message()->error_code() != M2MBlockMessage::ErrorNone) { 00576 block_message()->clear_values(); 00577 } 00578 } 00579 } 00580 #endif 00581 // Firmware object uri path is limited to be max 255 bytes 00582 if ((strcmp(uri_path(), FIRMAWARE_PACKAGE_URI_PATH) == 0) && 00583 received_coap_header->payload_len > 255) { 00584 msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 00585 } else if ((strcmp(uri_path(), SERVER_LIFETIME_PATH) == 0)) { 00586 // Check that lifetime can't go below 60s 00587 char *query = (char*)alloc_string_copy(received_coap_header->payload_ptr, 00588 received_coap_header->payload_len); 00589 00590 if (query) { 00591 int32_t lifetime = atol(query); 00592 if (lifetime < MINIMUM_REGISTRATION_TIME) { 00593 tr_error("M2MResourceBase::handle_put_request() - lifetime value % " PRId32 " not acceptable", lifetime); 00594 msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE; 00595 } 00596 free(query); 00597 } 00598 else { 00599 // memory allocation for query fails 00600 tr_error("M2MResourceBase::handle_put_request() - Out of memory !!!"); 00601 msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR; 00602 } 00603 } 00604 00605 // Do not update resource value in error case. 00606 if ((received_coap_header->payload_ptr) && (msg_code == COAP_MSG_CODE_RESPONSE_CHANGED)) { 00607 execute_value_updated = true; 00608 } 00609 } 00610 } else { 00611 // Operation is not allowed. 00612 tr_error("M2MResourceBase::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED"); 00613 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00614 } 00615 } else { 00616 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; 00617 } 00618 if(coap_response) { 00619 coap_response->msg_code = msg_code; 00620 } 00621 00622 return coap_response; 00623 } 00624 00625 00626 #ifndef DISABLE_BLOCK_MESSAGE 00627 00628 M2MBlockMessage* M2MResourceBase::block_message() const 00629 { 00630 return _block_message_data; 00631 } 00632 00633 bool M2MResourceBase::set_incoming_block_message_callback(incoming_block_message_callback callback) 00634 { 00635 incoming_block_message_callback* old_callback = (incoming_block_message_callback*)M2MCallbackStorage::remove_callback(*this, 00636 M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback); 00637 delete old_callback; 00638 00639 // copy the callback object. This will change on next version to be a direct pointer to a interface class, 00640 // this FPn<> is just too heavy for this usage. 00641 incoming_block_message_callback* new_callback = new incoming_block_message_callback(callback); 00642 00643 delete _block_message_data; 00644 _block_message_data = NULL; 00645 _block_message_data = new M2MBlockMessage(); 00646 00647 return M2MCallbackStorage::add_callback(*this, 00648 new_callback, 00649 M2MCallbackAssociation::M2MResourceInstanceIncomingBlockMessageCallback); 00650 } 00651 00652 bool M2MResourceBase::set_outgoing_block_message_callback(outgoing_block_message_callback callback) 00653 { 00654 outgoing_block_message_callback *old_callback = (outgoing_block_message_callback*)M2MCallbackStorage::remove_callback(*this, 00655 M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback); 00656 delete old_callback; 00657 00658 outgoing_block_message_callback *new_callback = new outgoing_block_message_callback(callback); 00659 return M2MCallbackStorage::add_callback(*this, 00660 new_callback, 00661 M2MCallbackAssociation::M2MResourceInstanceOutgoingBlockMessageCallback); 00662 } 00663 #endif 00664 00665 bool M2MResourceBase::set_notification_sent_callback(notification_sent_callback callback) 00666 { 00667 notification_sent_callback *old_callback = (notification_sent_callback*)M2MCallbackStorage::remove_callback(*this, 00668 M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback); 00669 delete old_callback; 00670 00671 notification_sent_callback *new_callback = new notification_sent_callback(callback); 00672 return M2MCallbackStorage::add_callback(*this, 00673 new_callback, 00674 M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback); 00675 } 00676 00677 bool M2MResourceBase::set_notification_sent_callback(notification_sent_callback_2 callback) 00678 { 00679 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2); 00680 00681 return M2MCallbackStorage::add_callback(*this, 00682 (void*)callback, 00683 M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2); 00684 } 00685 00686 bool M2MResourceBase::set_notification_status_callback(notification_status_callback callback) 00687 { 00688 notification_status_callback *old_callback = (notification_status_callback*)M2MCallbackStorage::remove_callback(*this, 00689 M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback); 00690 delete old_callback; 00691 00692 notification_status_callback *new_callback = new notification_status_callback(callback); 00693 return M2MCallbackStorage::add_callback(*this, 00694 new_callback, 00695 M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback); 00696 } 00697 00698 bool M2MResourceBase::set_notification_status_callback(notification_status_callback_2 callback) 00699 { 00700 M2MCallbackStorage::remove_callback(*this, M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2); 00701 00702 return M2MCallbackStorage::add_callback(*this, 00703 (void*)callback, 00704 M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2); 00705 } 00706 00707 void M2MResourceBase::notification_sent() 00708 { 00709 // Now we will call both callbacks, if they are set. This is different from original behavior. 00710 notification_sent_callback* callback = 00711 (notification_sent_callback*)M2MCallbackStorage::get_callback(*this, 00712 M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback); 00713 if (callback) { 00714 (*callback)(); 00715 } 00716 00717 notification_sent_callback_2 callback2 = 00718 (notification_sent_callback_2)M2MCallbackStorage::get_callback(*this, 00719 M2MCallbackAssociation::M2MResourceInstanceNotificationSentCallback2); 00720 if (callback2) { 00721 (*callback2)(); 00722 } 00723 } 00724 00725 void M2MResourceBase::notification_status(const uint16_t msg_id, const NotificationStatus status) 00726 { 00727 if (_notification_status != status) { 00728 _notification_status = status; 00729 // Now we will call both callbacks, if they are set. This is different from original behavior. 00730 notification_status_callback* callback = 00731 (notification_status_callback*)M2MCallbackStorage::get_callback(*this, 00732 M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback); 00733 if (callback) { 00734 (*callback)(msg_id, status); 00735 } 00736 00737 notification_status_callback_2 callback2 = 00738 (notification_status_callback_2)M2MCallbackStorage::get_callback(*this, 00739 M2MCallbackAssociation::M2MResourceInstanceNotificationStatusCallback2); 00740 if (callback2) { 00741 (*callback2)(msg_id, status); 00742 } 00743 } 00744 } 00745 00746 M2MResourceBase::ResourceType M2MResourceBase::convert_data_type(M2MBase::DataType type) const 00747 { 00748 M2MResourceBase::ResourceType res_type = M2MResourceBase::OBJLINK; 00749 switch(type) { 00750 case M2MBase::STRING: 00751 res_type = M2MResourceBase::STRING; 00752 break; 00753 case M2MBase::INTEGER: 00754 res_type = M2MResourceBase::INTEGER; 00755 break; 00756 case M2MBase::FLOAT: 00757 res_type = M2MResourceBase::FLOAT; 00758 break; 00759 case M2MBase::OPAQUE: 00760 res_type = M2MResourceBase::OPAQUE; 00761 break; 00762 case M2MBase::BOOLEAN: 00763 res_type = M2MResourceBase::BOOLEAN; 00764 break; 00765 case M2MBase::TIME: 00766 res_type = M2MResourceBase::TIME; 00767 break; 00768 case M2MBase::OBJLINK: 00769 res_type = M2MResourceBase::OBJLINK; 00770 break; 00771 } 00772 return res_type; 00773 } 00774 00775 M2MResourceBase::NotificationStatus M2MResourceBase::notification_status() const 00776 { 00777 return _notification_status; 00778 } 00779 00780 void M2MResourceBase::clear_notification_status() 00781 { 00782 _notification_status = M2MResourceBase::INIT; 00783 }
Generated on Tue Jul 12 2022 19:01:35 by
1.7.2