Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mresource.cpp Source File

m2mresource.cpp

00001 /*
00002  * Copyright (c) 2015 ARM Limited. All rights reserved.
00003  * SPDX-License-Identifier: Apache-2.0
00004  * Licensed under the Apache License, Version 2.0 (the License); you may
00005  * not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  * http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
00012  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include "mbed-client/m2mconstants.h"
00017 #include "mbed-client/m2mresource.h"
00018 #include "mbed-client/m2mobservationhandler.h"
00019 #include "include/m2mreporthandler.h"
00020 #include "include/m2mtlvserializer.h"
00021 #include "include/m2mtlvdeserializer.h"
00022 #include "mbed-trace/mbed_trace.h"
00023 
00024 #include <stdlib.h>
00025 
00026 #define TRACE_GROUP "mClt"
00027 
00028 M2MResource::M2MResource(M2MObjectInstance &parent,
00029                          const String &resource_name,
00030                          M2MBase::Mode resource_mode,
00031                          const String &resource_type,
00032                          M2MBase::DataType type,
00033                          const uint8_t *value,
00034                          const uint8_t value_length,
00035                          char *path,
00036                          bool multiple_instance,
00037                          bool external_blockwise_store)
00038 : M2MResourceBase(resource_name, resource_mode, resource_type, type, value, value_length,
00039                       path, external_blockwise_store, multiple_instance),
00040   _parent(parent)
00041 #ifndef DISABLE_DELAYED_RESPONSE
00042   ,_delayed_token(NULL),
00043   _delayed_token_len(0),
00044   _delayed_response(false)
00045 #endif
00046 {
00047     M2MBase::set_base_type(M2MBase::Resource);
00048     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00049     M2MBase::set_observable(false);
00050     if (multiple_instance) {
00051         M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00052     }
00053 
00054 }
00055 
00056 M2MResource::M2MResource(M2MObjectInstance &parent,
00057                          const lwm2m_parameters_s* s,
00058                           M2MBase::DataType type)
00059 : M2MResourceBase(s, type),
00060   _parent(parent)
00061 #ifndef DISABLE_DELAYED_RESPONSE
00062   ,_delayed_token(NULL),
00063   _delayed_token_len(0),
00064   _delayed_response(false)
00065 #endif
00066 {
00067     // verify, that the client has hardcoded proper type to the structure
00068     assert(base_type() == M2MBase::Resource);
00069 }
00070 
00071 M2MResource::M2MResource(M2MObjectInstance &parent,
00072                          const String &resource_name,
00073                          M2MBase::Mode resource_mode,
00074                          const String &resource_type,
00075                          M2MBase::DataType type,
00076                          bool observable,
00077                          char *path,
00078                          bool multiple_instance,
00079                          bool external_blockwise_store)
00080 : M2MResourceBase(resource_name, resource_mode, resource_type, type,
00081                       path,
00082                       external_blockwise_store,multiple_instance),
00083   _parent(parent)
00084 #ifndef DISABLE_DELAYED_RESPONSE
00085   ,_delayed_token(NULL),
00086   _delayed_token_len(0),
00087   _delayed_response(false)
00088 #endif
00089 {
00090     M2MBase::set_base_type(M2MBase::Resource);
00091     M2MBase::set_operation(M2MBase::GET_PUT_ALLOWED);
00092     M2MBase::set_observable(observable);
00093     if (multiple_instance) {
00094         M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00095     }
00096 }
00097 
00098 
00099 M2MResource::~M2MResource()
00100 {
00101     if(!_resource_instance_list.empty()) {
00102         M2MResourceInstance* res = NULL;
00103         M2MResourceInstanceList::const_iterator it;
00104         it = _resource_instance_list.begin();
00105         for (; it!=_resource_instance_list.end(); it++ ) {
00106             //Free allocated memory for resources.
00107             res = *it;
00108             delete res;
00109         }
00110         _resource_instance_list.clear();
00111     }
00112 #ifndef DISABLE_DELAYED_RESPONSE
00113     free(_delayed_token);
00114 #endif
00115 
00116     free_resources();
00117 }
00118 
00119 bool M2MResource::supports_multiple_instances() const
00120 {
00121     M2MBase::lwm2m_parameters_s* param = M2MBase::get_lwm2m_parameters();
00122     return param->multiple_instance;
00123 }
00124 
00125 #ifndef DISABLE_DELAYED_RESPONSE
00126 void M2MResource::set_delayed_response(bool delayed_response)
00127 {
00128     _delayed_response = delayed_response;
00129 }
00130 
00131 bool M2MResource::send_delayed_post_response()
00132 {
00133     bool success = false;
00134     if(_delayed_response) {
00135         success = true;
00136         // At least on some unit tests the resource object is not fully constructed, which would
00137         // cause issues if the observation_handler is NULL. So do the check before dereferencing pointer.
00138         M2MObservationHandler* obs = observation_handler();
00139         if (obs) {
00140             obs->send_delayed_response(this);
00141         }
00142     }
00143     return success;
00144 }
00145 
00146 void M2MResource::get_delayed_token(uint8_t *&token, uint8_t &token_length)
00147 {
00148     token_length = 0;
00149     if(token) {
00150         free(token);
00151         token = NULL;
00152     }
00153     if(_delayed_token && _delayed_token_len > 0) {
00154         token = alloc_copy(_delayed_token, _delayed_token_len);
00155         if(token) {
00156             token_length = _delayed_token_len;
00157         }
00158     }
00159 }
00160 #endif
00161 
00162 bool M2MResource::remove_resource_instance(uint16_t inst_id)
00163 {
00164     tr_debug("M2MResource::remove_resource(inst_id %d)", inst_id);
00165     bool success = false;
00166     if(!_resource_instance_list.empty()) {
00167         M2MResourceInstance* res = NULL;
00168         M2MResourceInstanceList::const_iterator it;
00169         it = _resource_instance_list.begin();
00170         int pos = 0;
00171         for ( ; it != _resource_instance_list.end(); it++, pos++ ) {
00172             if(((*it)->instance_id() == inst_id)) {
00173                 // Resource found and deleted.
00174                 res = *it;
00175                 delete res;
00176                 _resource_instance_list.erase(pos);
00177                 set_changed();
00178                 success = true;
00179                 break;
00180             }
00181         }
00182     }
00183     return success;
00184 }
00185 
00186 M2MResourceInstance* M2MResource::resource_instance(uint16_t inst_id) const
00187 {
00188     tr_debug("M2MResource::resource(resource_name inst_id %d)", inst_id);
00189     M2MResourceInstance *res = NULL;
00190     if(!_resource_instance_list.empty()) {
00191         M2MResourceInstanceList::const_iterator it;
00192         it = _resource_instance_list.begin();
00193         for ( ; it != _resource_instance_list.end(); it++ ) {
00194             if(((*it)->instance_id() == inst_id)) {
00195                 // Resource found.
00196                 res = *it;
00197                 break;
00198             }
00199         }
00200     }
00201     return res;
00202 }
00203 
00204 const M2MResourceInstanceList& M2MResource::resource_instances() const
00205 {
00206     return _resource_instance_list;
00207 }
00208 
00209 uint16_t M2MResource::resource_instance_count() const
00210 {
00211     return (uint16_t)_resource_instance_list.size();
00212 }
00213 
00214 #ifndef DISABLE_DELAYED_RESPONSE
00215 bool M2MResource::delayed_response() const
00216 {
00217     return _delayed_response;
00218 }
00219 #endif
00220 
00221 M2MObservationHandler* M2MResource::observation_handler() const
00222 {
00223     const M2MObjectInstance& parent_object_instance = get_parent_object_instance();
00224 
00225     // XXX: need to check the flag too
00226     return parent_object_instance.observation_handler();
00227 }
00228 
00229 void M2MResource::set_observation_handler(M2MObservationHandler *handler)
00230 {
00231     M2MObjectInstance& parent_object_instance = get_parent_object_instance();
00232 
00233     // XXX: need to set the flag too
00234     parent_object_instance.set_observation_handler(handler);
00235 }
00236 
00237 bool M2MResource::handle_observation_attribute(const char *query)
00238 {
00239     tr_debug("M2MResource::handle_observation_attribute - is_under_observation(%d)", is_under_observation());
00240     bool success = false;
00241     M2MReportHandler *handler = M2MBase::report_handler();
00242     if (!handler) {
00243         handler = M2MBase::create_report_handler();
00244     }
00245 
00246     if (handler) {
00247         success = handler->parse_notification_attribute(query,
00248                 M2MBase::base_type(), resource_instance_type());
00249         if (success) {
00250             if (is_under_observation()) {
00251                 handler->set_under_observation(true);
00252             }
00253         }
00254         else {
00255             handler->set_default_values();
00256         }
00257 
00258         if (success) {
00259             if(!_resource_instance_list.empty()) {
00260                 M2MResourceInstanceList::const_iterator it;
00261                 it = _resource_instance_list.begin();
00262                 for ( ; it != _resource_instance_list.end(); it++ ) {
00263                     M2MReportHandler *report_handler = (*it)->report_handler();
00264                     if(report_handler && is_under_observation()) {
00265                         report_handler->set_notification_trigger();
00266                     }
00267                 }
00268             }
00269         }
00270     }
00271     return success;
00272 }
00273 
00274 void M2MResource::add_observation_level(M2MBase::Observation observation_level)
00275 {
00276     M2MBase::add_observation_level(observation_level);
00277     if(!_resource_instance_list.empty()) {
00278         M2MResourceInstanceList::const_iterator inst;
00279         inst = _resource_instance_list.begin();
00280         for ( ; inst != _resource_instance_list.end(); inst++ ) {
00281             (*inst)->add_observation_level(observation_level);
00282         }
00283     }
00284 }
00285 
00286 void M2MResource::remove_observation_level(M2MBase::Observation observation_level)
00287 {
00288     M2MBase::remove_observation_level(observation_level);
00289     if(!_resource_instance_list.empty()) {
00290         M2MResourceInstanceList::const_iterator inst;
00291         inst = _resource_instance_list.begin();
00292         for ( ; inst != _resource_instance_list.end(); inst++ ) {
00293             (*inst)->remove_observation_level(observation_level);
00294         }
00295     }
00296 }
00297 
00298 void M2MResource::add_resource_instance(M2MResourceInstance *res)
00299 {
00300     tr_debug("M2MResource::add_resource_instance()");
00301     if(res) {
00302         _resource_instance_list.push_back(res);
00303         set_changed();
00304     }
00305 }
00306 
00307 sn_coap_hdr_s* M2MResource::handle_get_request(nsdl_s *nsdl,
00308                                                sn_coap_hdr_s *received_coap_header,
00309                                                M2MObservationHandler *observation_handler)
00310 {
00311     tr_info("M2MResource::handle_get_request()");
00312     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00313     sn_coap_hdr_s * coap_response = NULL;
00314     if(supports_multiple_instances()) {
00315         coap_response = sn_nsdl_build_response(nsdl,
00316                                                received_coap_header,
00317                                                msg_code);
00318         if(received_coap_header) {
00319             // process the GET if we have registered a callback for it
00320             if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
00321                 if(coap_response) {
00322                     bool content_type_present = false;
00323                     bool is_content_type_supported = true;
00324 
00325                     if (received_coap_header->options_list_ptr &&
00326                             received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
00327                         content_type_present = true;
00328                         coap_response->content_format = received_coap_header->options_list_ptr->accept;
00329                     }
00330 
00331                     // Check if preferred content type is supported
00332                     if (content_type_present) {
00333                         if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
00334                             coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
00335                             is_content_type_supported = false;
00336                         }
00337                     }
00338 
00339                     if (is_content_type_supported) {
00340                         if(!content_type_present &&
00341                            (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00342                             M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00343                             coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
00344                         }
00345 
00346                         tr_debug("M2MResource::handle_get_request() - Request Content-type: %d", coap_response->content_format);
00347 
00348                         uint8_t *data = NULL;
00349                         uint32_t data_length = 0;
00350                         // fill in the CoAP response payload
00351                         if(COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format ||
00352                            COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
00353                             set_coap_content_type(coap_response->content_format);
00354                             data = M2MTLVSerializer::serialize(this, data_length);
00355                         }
00356 
00357                         coap_response->payload_len = data_length;
00358                         coap_response->payload_ptr = data;
00359 
00360                         coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00361                         if (coap_response->options_list_ptr) {
00362                             coap_response->options_list_ptr->max_age = max_age();
00363                         }
00364 
00365                         if(received_coap_header->options_list_ptr) {
00366                             if(received_coap_header->options_list_ptr->observe != -1) {
00367                                 if (is_observable()) {
00368                                     uint32_t number = 0;
00369                                     uint8_t observe_option = 0;
00370                                     observe_option = received_coap_header->options_list_ptr->observe;
00371                                     if(START_OBSERVATION == observe_option) {
00372                                         // If the observe length is 0 means register for observation.
00373                                         if(received_coap_header->options_list_ptr->observe != -1) {
00374                                             number = received_coap_header->options_list_ptr->observe;
00375                                         }
00376 
00377                                         // If the observe value is 0 means register for observation.
00378                                         if(number == 0) {
00379                                             tr_info("M2MResource::handle_get_request - put resource under observation");
00380                                             M2MResourceInstanceList::const_iterator it;
00381                                             it = _resource_instance_list.begin();
00382                                             for (; it!=_resource_instance_list.end(); it++ ) {
00383                                                 (*it)->add_observation_level(M2MBase::R_Attribute);
00384                                             }
00385                                             set_under_observation(true,observation_handler);
00386                                             M2MBase::add_observation_level(M2MBase::R_Attribute);
00387                                             send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
00388                                             if (coap_response->options_list_ptr) {
00389                                                 coap_response->options_list_ptr->observe = observation_number();
00390                                             }
00391                                         }
00392 
00393                                         if(received_coap_header->token_ptr) {
00394                                             set_observation_token(received_coap_header->token_ptr,
00395                                                                   received_coap_header->token_len);
00396                                         }
00397 
00398                                     } else if (STOP_OBSERVATION == observe_option) {
00399                                         tr_info("M2MResource::handle_get_request - stops observation");
00400                                         set_under_observation(false,NULL);
00401                                         M2MBase::remove_observation_level(M2MBase::R_Attribute);
00402                                         send_notification_delivery_status(*this,NOTIFICATION_STATUS_UNSUBSCRIBED);
00403                                         M2MResourceInstanceList::const_iterator it;
00404                                         it = _resource_instance_list.begin();
00405                                         for (; it!=_resource_instance_list.end(); it++ ) {
00406                                             (*it)->remove_observation_level(M2MBase::R_Attribute);
00407                                         }
00408                                     }
00409                                     msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00410                                 } else {
00411                                     msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00412                                 }
00413                             }
00414                         }
00415                     } else {
00416                         tr_error("M2MResource::handle_get_request() - Content-Type %d not supported", coap_response->content_format);
00417                         msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
00418                     }
00419                 }
00420             } else {
00421                 tr_error("M2MResource::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00422                 // Operation is not allowed.
00423                 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00424             }
00425         }
00426         if(coap_response) {
00427             coap_response->msg_code = msg_code;
00428         }
00429     } else {
00430         coap_response = M2MResourceBase::handle_get_request(nsdl,
00431                             received_coap_header,
00432                             observation_handler);
00433     }
00434     return coap_response;
00435 }
00436 
00437 sn_coap_hdr_s* M2MResource::handle_put_request(nsdl_s *nsdl,
00438                                                sn_coap_hdr_s *received_coap_header,
00439                                                M2MObservationHandler *observation_handler,
00440                                                bool &execute_value_updated)
00441 {
00442     tr_info("M2MResource::handle_put_request()");
00443     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00444     sn_coap_hdr_s * coap_response = NULL;
00445     if(supports_multiple_instances()) {
00446         coap_response = sn_nsdl_build_response(nsdl,
00447                                                received_coap_header,
00448                                                msg_code);
00449         // process the PUT if we have registered a callback for it
00450         if(received_coap_header) {
00451             uint16_t coap_content_type = 0;
00452             bool content_type_present = false;
00453             if(received_coap_header->content_format != COAP_CT_NONE && coap_response) {
00454                 content_type_present = true;
00455                 coap_content_type = received_coap_header->content_format;
00456             }
00457             if(received_coap_header->options_list_ptr &&
00458                received_coap_header->options_list_ptr->uri_query_ptr) {
00459                 char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
00460                                                         received_coap_header->options_list_ptr->uri_query_len);
00461                 if (query){
00462                     msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
00463                     tr_info("M2MResource::handle_put_request() - query %s", query);
00464                     // if anything was updated, re-initialize the stored notification attributes
00465                     if (!handle_observation_attribute(query)){
00466                         tr_debug("M2MResource::handle_put_request() - Invalid query");
00467                         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
00468                     }
00469                     free(query);
00470                 }
00471             } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
00472                 if(!content_type_present &&
00473                    (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00474                     M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00475                     coap_content_type = COAP_CONTENT_OMA_TLV_TYPE;
00476                 }
00477 
00478                 tr_debug("M2MResource::handle_put_request() - Request Content-type: %d", coap_content_type);
00479 
00480                 if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
00481                    COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
00482                     set_coap_content_type(coap_content_type);
00483                     M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
00484                     error = M2MTLVDeserializer::deserialize_resource_instances(received_coap_header->payload_ptr,
00485                                                                          received_coap_header->payload_len,
00486                                                                          *this,
00487                                                                          M2MTLVDeserializer::Put);
00488                     switch(error) {
00489                         case M2MTLVDeserializer::None:
00490                             if(observation_handler) {
00491                                 String value = "";
00492                                 if (received_coap_header->uri_path_ptr != NULL &&
00493                                     received_coap_header->uri_path_len > 0) {
00494 
00495                                     value.append_raw((char*)received_coap_header->uri_path_ptr,received_coap_header->uri_path_len);
00496                                 }
00497                                 execute_value_updated = true;
00498                             }
00499                             msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
00500                             break;
00501                         case M2MTLVDeserializer::NotFound:
00502                             msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00503                             break;
00504                         case M2MTLVDeserializer::NotAllowed:
00505                             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00506                             break;
00507                         case M2MTLVDeserializer::NotValid:
00508                             msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00509                             break;
00510                         case M2MTLVDeserializer::OutOfMemory:
00511                             msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
00512                             break;
00513                     }
00514                 } else {
00515                     msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00516                 } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
00517             } else {
00518                 // Operation is not allowed.
00519                 tr_error("M2MResource::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00520                 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00521             }
00522         } else {
00523             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00524         }
00525         if(coap_response) {
00526             coap_response->msg_code = msg_code;
00527         }
00528     } else {
00529         coap_response = M2MResourceBase::handle_put_request(nsdl,
00530                             received_coap_header,
00531                             observation_handler,
00532                             execute_value_updated);
00533     }
00534     return coap_response;
00535 }
00536 
00537 
00538 sn_coap_hdr_s* M2MResource::handle_post_request(nsdl_s *nsdl,
00539                                                 sn_coap_hdr_s *received_coap_header,
00540                                                 M2MObservationHandler */*observation_handler*/,
00541                                                 bool &/*execute_value_updated*/,
00542                                                 sn_nsdl_addr_s *address)
00543 {
00544     tr_info("M2MResource::handle_post_request()");
00545     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00546     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00547                                                            received_coap_header,
00548                                                            msg_code);
00549 
00550     // process the POST if we have registered a callback for it
00551     if(received_coap_header) {
00552         if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
00553             M2MResource::M2MExecuteParameter exec_params(object_name(), name(), object_instance_id());
00554 
00555             uint16_t coap_content_type = 0;
00556             if(received_coap_header->payload_ptr) {
00557                 if(received_coap_header->content_format != COAP_CT_NONE) {
00558                     coap_content_type = received_coap_header->content_format;
00559                 }
00560 
00561                 if(coap_content_type == COAP_CT_TEXT_PLAIN) {
00562                     exec_params._value = received_coap_header->payload_ptr;
00563                     if (exec_params._value) {
00564                         exec_params._value_length = received_coap_header->payload_len;
00565                     }
00566                 } else {
00567                     msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00568                 }
00569             }
00570             if(COAP_MSG_CODE_RESPONSE_CHANGED == msg_code) {
00571                 tr_debug("M2MResource::handle_post_request - Execute resource function");
00572 #ifndef DISABLE_DELAYED_RESPONSE
00573                 if (coap_response) {
00574                     if(_delayed_response) {
00575                         if(received_coap_header->token_len) {
00576                             free(_delayed_token);
00577                             _delayed_token = NULL;
00578                             _delayed_token_len = 0;
00579                             _delayed_token = alloc_copy(received_coap_header->token_ptr, received_coap_header->token_len);
00580                             if(_delayed_token) {
00581                                 _delayed_token_len = received_coap_header->token_len;
00582                             }
00583                         }
00584                     } else {
00585     #endif
00586                         uint32_t length = 0;
00587                         get_value(coap_response->payload_ptr, length);
00588                         coap_response->payload_len = length;
00589     #ifndef DISABLE_DELAYED_RESPONSE
00590                     }
00591                 }
00592 #endif
00593                 execute(&exec_params);
00594             }
00595 
00596         } else { // if ((object->operation() & SN_GRS_POST_ALLOWED) != 0)
00597             tr_error("M2MResource::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00598             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.05
00599         }
00600     } else { //if(object && received_coap_header)
00601         tr_error("M2MResource::handle_post_request - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00602         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED; // 4.01
00603     }
00604     if(coap_response) {
00605         coap_response->msg_code = msg_code;
00606     }
00607     return coap_response;
00608 }
00609 
00610 M2MBase *M2MResource::get_parent() const
00611 {
00612     return (M2MBase *) &get_parent_object_instance();
00613 }
00614 
00615 M2MObjectInstance& M2MResource::get_parent_object_instance() const
00616 {
00617     return _parent;
00618 }
00619 
00620 uint16_t M2MResource::object_instance_id() const
00621 {
00622     const M2MObjectInstance& parent_object_instance = get_parent_object_instance();
00623     return parent_object_instance.instance_id();
00624 }
00625 
00626 M2MResource& M2MResource::get_parent_resource() const
00627 {
00628     return (M2MResource&)*this;
00629 }
00630 
00631 const char* M2MResource::object_name() const
00632 {
00633     const M2MObjectInstance& parent_object_instance = _parent;
00634     const M2MObject& parent_object = parent_object_instance.get_parent_object();
00635 
00636     return parent_object.name();
00637 }
00638 
00639 #ifdef MEMORY_OPTIMIZED_API
00640 M2MResource::M2MExecuteParameter::M2MExecuteParameter(const char *object_name, const char *resource_name,
00641                                                         uint16_t object_instance_id) :
00642 _object_name(object_name),
00643 _resource_name(resource_name),
00644 _value(NULL),
00645 _value_length(0),
00646 _object_instance_id(object_instance_id)
00647 {
00648 }
00649 #else
00650 M2MResource::M2MExecuteParameter::M2MExecuteParameter(const String &object_name, const String &resource_name,
00651                                                         uint16_t object_instance_id) :
00652 _object_name(object_name),
00653 _resource_name(resource_name),
00654 _value(NULL),
00655 _value_length(0),
00656 _object_instance_id(object_instance_id)
00657 {
00658 }
00659 #endif
00660 
00661 // These could be actually changed to be inline ones, as it would likely generate
00662 // smaller code at application side.
00663 
00664 const uint8_t *M2MResource::M2MExecuteParameter::get_argument_value() const
00665 {
00666     return _value;
00667 }
00668 
00669 uint16_t M2MResource::M2MExecuteParameter::get_argument_value_length() const
00670 {
00671     return _value_length;
00672 }
00673 
00674 #ifdef MEMORY_OPTIMIZED_API
00675 const char* M2MResource::M2MExecuteParameter::get_argument_object_name() const
00676 {
00677     return _object_name;
00678 }
00679 
00680 const char* M2MResource::M2MExecuteParameter::get_argument_resource_name() const
00681 {
00682     return _resource_name;
00683 }
00684 #else
00685 const String& M2MResource::M2MExecuteParameter::get_argument_object_name() const
00686 {
00687     return _object_name;
00688 }
00689 
00690 const String& M2MResource::M2MExecuteParameter::get_argument_resource_name() const
00691 {
00692     return _resource_name;
00693 }
00694 #endif
00695 
00696 uint16_t M2MResource::M2MExecuteParameter::get_argument_object_instance_id() const
00697 {
00698     return _object_instance_id;
00699 }