Simple interface for Mbed Cloud Client
Embed:
(wiki syntax)
Show/hide line numbers
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