Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2mobjectinstance.cpp Source File

m2mobjectinstance.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/m2mobjectinstance.h"
00017 #include "mbed-client/m2mobject.h"
00018 #include "mbed-client/m2mconstants.h"
00019 #include "mbed-client/m2mresource.h"
00020 #include "mbed-client/m2mresource.h"
00021 #include "mbed-client/m2mobservationhandler.h"
00022 #include "mbed-client/m2mstring.h"
00023 #include "mbed-client/m2mstringbuffer.h"
00024 #include "include/m2mtlvserializer.h"
00025 #include "include/m2mtlvdeserializer.h"
00026 #include "include/m2mreporthandler.h"
00027 #include "mbed-trace/mbed_trace.h"
00028 #include "include/m2mcallbackstorage.h"
00029 #include <stdlib.h>
00030 
00031 #define BUFFER_SIZE 10
00032 #define TRACE_GROUP "mClt"
00033 
00034 M2MObjectInstance::M2MObjectInstance(M2MObject& parent,
00035                                      const String &resource_type,
00036                                      char *path,
00037                                      bool external_blockwise_store)
00038 : M2MBase("",
00039           M2MBase::Dynamic,
00040 #ifndef DISABLE_RESOURCE_TYPE
00041           resource_type,
00042 #endif
00043           path,
00044           external_blockwise_store,
00045           false),
00046   _parent(parent)
00047 {
00048     M2MBase::set_base_type(M2MBase::ObjectInstance);
00049     M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00050     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00051 }
00052 
00053 M2MObjectInstance::M2MObjectInstance(M2MObject& parent, const lwm2m_parameters_s* static_res)
00054 : M2MBase(static_res), _parent(parent)
00055 {
00056     M2MBase::set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00057     M2MBase::set_operation(M2MBase::GET_ALLOWED);
00058 }
00059 
00060 M2MObjectInstance::~M2MObjectInstance()
00061 {
00062     if(!_resource_list.empty()) {
00063         M2MResource* res = NULL;
00064         M2MResourceList::const_iterator it;
00065         it = _resource_list.begin();
00066         for (; it!=_resource_list.end(); it++ ) {
00067             //Free allocated memory for resources.
00068             res = *it;
00069             delete res;
00070         }
00071         _resource_list.clear();
00072     }
00073 
00074     free_resources();
00075 }
00076 
00077 // TBD, ResourceType to the base class struct?? TODO!
00078 M2MResource* M2MObjectInstance::create_static_resource(const lwm2m_parameters_s* static_res,
00079                                                        M2MResourceInstance::ResourceType type)
00080 {
00081     tr_debug("M2MObjectInstance::create_static_resource(lwm2m_parameters_s resource_name %s)", static_res->identifier.name);
00082     M2MResource *res = NULL;
00083     if (validate_string_length(static_res->identifier.name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00084         return res;
00085     }
00086     if(!resource(static_res->identifier.name)) {
00087         res = new M2MResource(*this, static_res, convert_resource_type(type));
00088         if(res) {
00089             res->add_observation_level(observation_level());
00090             //if (multiple_instance) {
00091                 //res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00092             //}
00093             _resource_list.push_back(res);
00094         }
00095     }
00096     return res;
00097 }
00098 
00099 M2MResource* M2MObjectInstance::create_static_resource(const String &resource_name,
00100                                                        const String &resource_type,
00101                                                        M2MResourceInstance::ResourceType type,
00102                                                        const uint8_t *value,
00103                                                        const uint8_t value_length,
00104                                                        bool multiple_instance,
00105                                                        bool external_blockwise_store)
00106 {
00107     tr_debug("M2MObjectInstance::create_static_resource(resource_name %s)",resource_name.c_str());
00108     M2MResource *res = NULL;
00109     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00110         return res;
00111     }
00112     if(!resource(resource_name)) {
00113         char *path = create_path(*this, resource_name.c_str());
00114 
00115         if (path) {
00116             res = new M2MResource(*this, resource_name, M2MBase::Static, resource_type, convert_resource_type(type),
00117                                   value, value_length, path,
00118                                   multiple_instance, external_blockwise_store);
00119             if(res) {
00120                 res->add_observation_level(observation_level());
00121                 if (multiple_instance) {
00122                     res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00123                 }
00124                 _resource_list.push_back(res);
00125             }
00126         }
00127     }
00128     return res;
00129 }
00130 
00131 M2MResource* M2MObjectInstance::create_dynamic_resource(const lwm2m_parameters_s* static_res,
00132                                                         M2MResourceInstance::ResourceType type,
00133                                                         bool observable)
00134 {
00135     tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)", static_res->identifier.name);
00136     M2MResource *res = NULL;
00137 
00138     if (validate_string_length(static_res->identifier.name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00139         return res;
00140     }
00141     if(!resource(static_res->identifier.name)) {
00142         res = new M2MResource(*this, static_res, convert_resource_type(type));
00143         if(res) {
00144             //if (multiple_instance) { // TODO!
00145               //  res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE);
00146             //}
00147             res->add_observation_level(observation_level());
00148             _resource_list.push_back(res);
00149         }
00150     }
00151     return res;
00152 }
00153 
00154 M2MResource* M2MObjectInstance::create_dynamic_resource(const String &resource_name,
00155                                                 const String &resource_type,
00156                                                 M2MResourceInstance::ResourceType type,
00157                                                 bool observable,
00158                                                 bool multiple_instance,
00159                                                 bool external_blockwise_store)
00160 {
00161     tr_debug("M2MObjectInstance::create_dynamic_resource(resource_name %s)",resource_name.c_str());
00162     M2MResource *res = NULL;
00163     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00164         return res;
00165     }
00166     if(!resource(resource_name)) {
00167         char *path = create_path(*this, resource_name.c_str());
00168         if (path) {
00169             res = new M2MResource(*this, resource_name, M2MBase::Dynamic, resource_type, convert_resource_type(type),
00170                                   observable, path,
00171                                   multiple_instance, external_blockwise_store);
00172             if(res) {
00173                 if (multiple_instance) {
00174                     res->set_coap_content_type(COAP_CONTENT_OMA_TLV_TYPE_OLD);
00175                 }
00176                 res->add_observation_level(observation_level());
00177                 _resource_list.push_back(res);
00178             }
00179         }
00180     }
00181     return res;
00182 }
00183 
00184 M2MResourceInstance* M2MObjectInstance::create_static_resource_instance(const String &resource_name,
00185                                                                         const String &resource_type,
00186                                                                         M2MResourceInstance::ResourceType type,
00187                                                                         const uint8_t *value,
00188                                                                         const uint8_t value_length,
00189                                                                         uint16_t instance_id,
00190                                                                         bool external_blockwise_store)
00191 {
00192     tr_debug("M2MObjectInstance::create_static_resource_instance(resource_name %s)",resource_name.c_str());
00193     M2MResourceInstance *instance = NULL;
00194     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00195 
00196         return instance;
00197     }
00198     M2MResource *res = resource(resource_name);
00199     if(!res) {
00200         char *path = create_path(*this, resource_name.c_str());
00201         if (path) {
00202             res = new M2MResource(*this, resource_name, M2MBase::Static, resource_type, convert_resource_type(type),
00203                                   value, value_length, path,
00204                                   true, external_blockwise_store);
00205             _resource_list.push_back(res);
00206             res->set_operation(M2MBase::GET_ALLOWED);
00207             res->set_observable(false);
00208             res->set_register_uri(false);
00209         }
00210     }
00211     if(res && res->supports_multiple_instances()&& (res->resource_instance(instance_id) == NULL)) {
00212         char *path = M2MBase::create_path(*res, instance_id);
00213         if (path) {
00214             instance = new M2MResourceInstance(*res, "", M2MBase::Static, resource_type, convert_resource_type(type),
00215                                                value, value_length,
00216                                                path, external_blockwise_store,true);
00217             if(instance) {
00218                 instance->set_operation(M2MBase::GET_ALLOWED);
00219                 instance->set_instance_id(instance_id);
00220                 res->add_resource_instance(instance);
00221             }
00222         }
00223     }
00224     return instance;
00225 }
00226 
00227 M2MResourceInstance* M2MObjectInstance::create_dynamic_resource_instance(const String &resource_name,
00228                                                                          const String &resource_type,
00229                                                                          M2MResourceInstance::ResourceType type,
00230                                                                          bool observable,
00231                                                                          uint16_t instance_id,
00232                                                                          bool external_blockwise_store)
00233 {
00234     tr_debug("M2MObjectInstance::create_dynamic_resource_instance(resource_name %s)",resource_name.c_str());
00235     M2MResourceInstance *instance = NULL;
00236     if (validate_string_length(resource_name, 1, MAX_ALLOWED_STRING_LENGTH) == false) {
00237         return instance;
00238     }
00239     M2MResource *res = resource(resource_name);
00240     if(!res) {
00241         char *path = create_path(*this, resource_name.c_str());
00242         if (path) {
00243             res = new M2MResource(*this, resource_name, M2MBase::Dynamic, resource_type, convert_resource_type(type),
00244                                   false, path, true, external_blockwise_store);
00245             _resource_list.push_back(res);
00246             res->set_register_uri(false);
00247             res->set_operation(M2MBase::GET_ALLOWED);
00248         }
00249     }
00250     if (res && res->supports_multiple_instances() && (res->resource_instance(instance_id) == NULL)) {
00251         char *path = create_path(*res, instance_id);
00252         if (path) {
00253             instance = new M2MResourceInstance(*res, "", M2MBase::Dynamic, resource_type, convert_resource_type(type),
00254                                                path, external_blockwise_store,true);
00255             if(instance) {
00256                 instance->set_operation(M2MBase::GET_ALLOWED);
00257                 instance->set_observable(observable);
00258                 instance->set_instance_id(instance_id);
00259                 res->add_resource_instance(instance);
00260             }
00261         }
00262     }
00263     return instance;
00264 }
00265 
00266 bool M2MObjectInstance::remove_resource(const String &resource_name)
00267 {
00268     return remove_resource(resource_name.c_str());
00269 }
00270 
00271 bool M2MObjectInstance::remove_resource(const char *resource_name)
00272 {
00273     tr_debug("M2MObjectInstance::remove_resource(resource_name %s)", resource_name);
00274 
00275     bool success = false;
00276     if(!_resource_list.empty()) {
00277          M2MResource* res = NULL;
00278          M2MResourceList::const_iterator it;
00279          it = _resource_list.begin();
00280          int pos = 0;
00281          for ( ; it != _resource_list.end(); it++, pos++ ) {
00282              if(strcmp((*it)->name(), resource_name) == 0) {
00283                 // Resource found and deleted.
00284                 res = *it;
00285                 delete res;
00286                 _resource_list.erase(pos);
00287                 success = true;
00288                 break;
00289              }
00290          }
00291     }
00292     return success;
00293 }
00294 
00295 bool M2MObjectInstance::remove_resource_instance(const String &resource_name,
00296                                                  uint16_t inst_id)
00297 {
00298     tr_debug("M2MObjectInstance::remove_resource_instance(resource_name %s inst_id %d)",
00299              resource_name.c_str(), inst_id);
00300     bool success = false;
00301     M2MResource *res = resource(resource_name);
00302     if(res) {
00303         M2MResourceInstanceList list = res->resource_instances();
00304         M2MResourceInstanceList::const_iterator it;
00305         it = list.begin();
00306         for ( ; it != list.end(); it++) {
00307             if((*it)->instance_id() == inst_id) {
00308                 success = res->remove_resource_instance(inst_id);
00309                 if(res->resource_instance_count() == 0) {
00310                     M2MResourceList::const_iterator itr;
00311                     itr = _resource_list.begin();
00312                     int pos = 0;
00313                     for ( ; itr != _resource_list.end(); itr++, pos++ ) {
00314                         if(strcmp((*itr)->name(),resource_name.c_str()) == 0) {
00315                             delete res;
00316                             _resource_list.erase(pos);
00317                             break;
00318                         }
00319                     }
00320                 }
00321                 break;
00322             }
00323         }
00324     }
00325     return success;
00326 }
00327 
00328 M2MResource* M2MObjectInstance::resource(const String &resource_name) const
00329 {
00330     return resource(resource_name.c_str());
00331 }
00332 
00333 M2MResource* M2MObjectInstance::resource(const char *resource_name) const
00334 {
00335     M2MResource *res = NULL;
00336     if(!_resource_list.empty()) {
00337         M2MResourceList::const_iterator it;
00338         it = _resource_list.begin();
00339         for (; it!=_resource_list.end(); it++ ) {
00340             if(strcmp((*it)->name(), resource_name) == 0) {
00341                 res = *it;
00342                 break;
00343             }
00344         }
00345     }
00346     return res;
00347 }
00348 
00349 const M2MResourceList& M2MObjectInstance::resources() const
00350 {
00351     return _resource_list;
00352 }
00353 
00354 uint16_t M2MObjectInstance::resource_count() const
00355 {
00356     uint16_t count = 0;
00357     if(!_resource_list.empty()) {
00358         M2MResourceList::const_iterator it;
00359         it = _resource_list.begin();
00360         for ( ; it != _resource_list.end(); it++ ) {
00361             if((*it)->supports_multiple_instances()) {
00362                 count += (*it)->resource_instance_count();
00363             } else {
00364                 count++;
00365             }
00366         }
00367     }
00368     return count;
00369 }
00370 
00371 uint16_t M2MObjectInstance::resource_count(const String& resource) const
00372 {
00373 
00374     return resource_count(resource.c_str());
00375 }
00376 
00377 uint16_t M2MObjectInstance::resource_count(const char *resource) const
00378 {
00379     uint16_t count = 0;
00380     if(!_resource_list.empty()) {
00381         M2MResourceList::const_iterator it;
00382         it = _resource_list.begin();
00383         for ( ; it != _resource_list.end(); it++ ) {
00384             if(strcmp((*it)->name(), resource) == 0) {
00385                 if((*it)->supports_multiple_instances()) {
00386                     count += (*it)->resource_instance_count();
00387                 } else {
00388                     count++;
00389                 }
00390             }
00391         }
00392     }
00393     return count;
00394 }
00395 
00396 M2MObservationHandler* M2MObjectInstance::observation_handler() const
00397 {
00398     // XXX: need to check the flag too
00399     return _parent.observation_handler();
00400 }
00401 
00402 void M2MObjectInstance::set_observation_handler(M2MObservationHandler *handler)
00403 {
00404     // XXX: need to set the flag too
00405     _parent.set_observation_handler(handler);
00406 }
00407 
00408 void M2MObjectInstance::add_observation_level(M2MBase::Observation observation_level)
00409 {
00410     M2MBase::add_observation_level(observation_level);
00411     if(!_resource_list.empty()) {
00412         M2MResourceList::const_iterator it;
00413         it = _resource_list.begin();
00414         for ( ; it != _resource_list.end(); it++ ) {
00415             (*it)->add_observation_level(observation_level);
00416         }
00417     }
00418 }
00419 
00420 void M2MObjectInstance::remove_observation_level(M2MBase::Observation observation_level)
00421 {
00422     M2MBase::remove_observation_level(observation_level);
00423     if(!_resource_list.empty()) {
00424         M2MResourceList::const_iterator it;
00425         it = _resource_list.begin();
00426         for ( ; it != _resource_list.end(); it++ ) {
00427            (*it)->remove_observation_level(observation_level);
00428         }
00429     }
00430 }
00431 
00432 sn_coap_hdr_s* M2MObjectInstance::handle_get_request(nsdl_s *nsdl,
00433                                                      sn_coap_hdr_s *received_coap_header,
00434                                                      M2MObservationHandler *observation_handler)
00435 {
00436     tr_info("M2MObjectInstance::handle_get_request()");
00437     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00438     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00439                                                            received_coap_header,
00440                                                            msg_code);
00441     uint8_t * data = NULL;
00442     uint32_t  data_length = 0;
00443 
00444     if (received_coap_header) {
00445         // process the GET if we have registered a callback for it
00446         if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
00447             if (coap_response) {
00448                 bool content_type_present = false;
00449                 bool is_content_type_supported = true;
00450 
00451                 if (received_coap_header->options_list_ptr &&
00452                         received_coap_header->options_list_ptr->accept != COAP_CT_NONE) {
00453                     content_type_present = true;
00454                     coap_response->content_format = received_coap_header->options_list_ptr->accept;
00455 
00456                 }
00457 
00458                 // Check if preferred content type is supported
00459                 if (content_type_present) {
00460                     if (coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE_OLD &&
00461                         coap_response->content_format != COAP_CONTENT_OMA_TLV_TYPE) {
00462                         is_content_type_supported = false;
00463                     }
00464                 }
00465 
00466                 if (is_content_type_supported) {
00467                     if (!content_type_present &&
00468                        (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00469                         M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00470                         coap_response->content_format = sn_coap_content_format_e(M2MBase::coap_content_type());
00471                     }
00472 
00473                     // fill in the CoAP response payload
00474                     if (COAP_CONTENT_OMA_TLV_TYPE == coap_response->content_format  ||
00475                         COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_response->content_format) {
00476                         set_coap_content_type(coap_response->content_format);
00477                         data = M2MTLVSerializer::serialize(_resource_list, data_length);
00478                     }
00479 
00480                     coap_response->payload_len = data_length;
00481                     coap_response->payload_ptr = data;
00482 
00483                     if (data) {
00484                         coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00485                         if (coap_response->options_list_ptr) {
00486                             coap_response->options_list_ptr->max_age = max_age();
00487                         }
00488 
00489                         if (received_coap_header->options_list_ptr) {
00490                             if (received_coap_header->options_list_ptr->observe != -1) {
00491                                 if (is_observable()) {
00492                                     uint32_t number = 0;
00493                                     uint8_t observe_option = 0;
00494                                     observe_option = received_coap_header->options_list_ptr->observe;
00495                                     if (START_OBSERVATION == observe_option) {
00496                                         // If the observe length is 0 means register for observation.
00497                                         if (received_coap_header->options_list_ptr->observe != -1) {
00498                                             number = received_coap_header->options_list_ptr->observe;
00499                                         }
00500 
00501                                         // If the observe value is 0 means register for observation.
00502                                         if (number == 0) {
00503                                             tr_info("M2MObjectInstance::handle_get_request - put resource under observation");
00504                                             set_under_observation(true,observation_handler);
00505                                             add_observation_level(M2MBase::OI_Attribute);
00506                                             send_notification_delivery_status(*this, NOTIFICATION_STATUS_SUBSCRIBED);
00507                                             if (coap_response->options_list_ptr) {
00508                                                 coap_response->options_list_ptr->observe = observation_number();
00509                                             }
00510                                         }
00511 
00512                                         if (received_coap_header->token_ptr) {
00513                                             set_observation_token(received_coap_header->token_ptr,
00514                                                                   received_coap_header->token_len);
00515                                         }
00516 
00517                                     } else if (STOP_OBSERVATION == observe_option) {
00518                                         tr_info("M2MObjectInstance::handle_get_request - stops observation");
00519                                         set_under_observation(false,NULL);
00520                                         remove_observation_level(M2MBase::OI_Attribute);
00521                                         send_notification_delivery_status(*this, NOTIFICATION_STATUS_UNSUBSCRIBED);
00522                                     }
00523                                     msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
00524                                 }
00525                                 else {
00526                                     msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00527                                 }
00528                             }
00529                         }
00530                     } else {
00531                         msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT; // Content format not supported
00532                     }
00533                 } else {
00534                     tr_error("M2MObjectInstance::handle_get_request() - Content-type: %d not supported", coap_response->content_format);
00535                     msg_code = COAP_MSG_CODE_RESPONSE_NOT_ACCEPTABLE;
00536                 }
00537             }
00538         } else {
00539             tr_error("M2MObjectInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00540             // Operation is not allowed.
00541             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00542         }
00543     } else {
00544         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00545     }
00546     if(coap_response) {
00547         coap_response->msg_code = msg_code;
00548     }
00549     return coap_response;
00550 }
00551 
00552 sn_coap_hdr_s* M2MObjectInstance::handle_put_request(nsdl_s *nsdl,
00553                                                      sn_coap_hdr_s *received_coap_header,
00554                                                      M2MObservationHandler *observation_handler,
00555                                                      bool &/*execute_value_updated*/)
00556 {
00557     tr_info("M2MObjectInstance::handle_put_request()");
00558     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00559     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00560                                                            received_coap_header,
00561                                                            msg_code);;
00562     if(received_coap_header) {
00563         uint16_t coap_content_type = 0;
00564         bool content_type_present = false;
00565 
00566         if(received_coap_header->content_format != COAP_CT_NONE) {
00567             content_type_present = true;
00568             set_coap_content_type(received_coap_header->content_format);
00569             if(coap_response) {
00570                 coap_content_type = received_coap_header->content_format;
00571             }
00572         }
00573         if(received_coap_header->options_list_ptr &&
00574            received_coap_header->options_list_ptr->uri_query_ptr) {
00575             char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
00576                                                     received_coap_header->options_list_ptr->uri_query_len);
00577             if (query){
00578                 tr_info("M2MObjectInstance::handle_put_request() - query %s", query);
00579                 // if anything was updated, re-initialize the stored notification attributes
00580                 if (!handle_observation_attribute(query)){
00581                     tr_debug("M2MObjectInstance::handle_put_request() - Invalid query");
00582                     msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
00583                 } else {
00584                     msg_code =COAP_MSG_CODE_RESPONSE_CHANGED;
00585                 }
00586                 free(query);
00587             }
00588         } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
00589             if(!content_type_present &&
00590                (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00591                 M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00592                 coap_content_type = M2MBase::coap_content_type();
00593             }
00594 
00595             tr_debug("M2MObjectInstance::handle_put_request() - Request Content-type: %d", coap_content_type);
00596 
00597             if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
00598                COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type ) {
00599                 set_coap_content_type(coap_content_type);
00600                 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
00601                 if(received_coap_header->payload_ptr) {
00602                     error = M2MTLVDeserializer::deserialize_resources(
00603                                 received_coap_header->payload_ptr,
00604                                 received_coap_header->payload_len, *this,
00605                                 M2MTLVDeserializer::Put);
00606                     switch(error) {
00607                         case M2MTLVDeserializer::None:
00608                             if(observation_handler) {
00609                                 observation_handler->value_updated(this);
00610                             }
00611                             msg_code = COAP_MSG_CODE_RESPONSE_CHANGED;
00612                             break;
00613                         case M2MTLVDeserializer::NotFound:
00614                             msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00615                             break;
00616                         case M2MTLVDeserializer::NotAllowed:
00617                             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00618                             break;
00619                         case M2MTLVDeserializer::NotValid:
00620                             msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00621                             break;
00622                         case M2MTLVDeserializer::OutOfMemory:
00623                             msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
00624                             break;
00625                     }
00626                 }
00627             } else {
00628                 msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00629             } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
00630         } else {
00631             // Operation is not allowed.
00632             tr_error("M2MObjectInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00633             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00634         }
00635     } else {
00636        msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00637     }
00638     if(coap_response) {
00639         coap_response->msg_code = msg_code;
00640     }
00641     return coap_response;
00642 }
00643 
00644 sn_coap_hdr_s* M2MObjectInstance::handle_post_request(nsdl_s *nsdl,
00645                                                       sn_coap_hdr_s *received_coap_header,
00646                                                       M2MObservationHandler *observation_handler,
00647                                                       bool &execute_value_updated,
00648                                                       sn_nsdl_addr_s *)
00649 {
00650     tr_info("M2MObjectInstance::handle_post_request()");
00651     sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
00652     sn_coap_hdr_s * coap_response = sn_nsdl_build_response(nsdl,
00653                                                            received_coap_header,
00654                                                            msg_code);
00655     if(received_coap_header) {
00656         if ((operation() & SN_GRS_POST_ALLOWED) != 0) {
00657             uint16_t coap_content_type = 0;
00658             bool content_type_present = false;
00659             if(received_coap_header->content_format != COAP_CT_NONE) {
00660                 set_coap_content_type(received_coap_header->content_format);
00661                 content_type_present = true;
00662                 if(coap_response) {
00663                     coap_content_type = received_coap_header->content_format;
00664                 }
00665             }
00666             if(!content_type_present &&
00667                (M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE ||
00668                 M2MBase::coap_content_type() == COAP_CONTENT_OMA_TLV_TYPE_OLD)) {
00669                 coap_content_type = M2MBase::coap_content_type();
00670             }
00671 
00672             tr_debug("M2MObjectInstance::handle_post_request() - Request Content-type: %d", coap_content_type);
00673 
00674             if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type ||
00675                COAP_CONTENT_OMA_TLV_TYPE_OLD == coap_content_type) {
00676                 set_coap_content_type(coap_content_type);
00677                 M2MTLVDeserializer::Error error = M2MTLVDeserializer::None;
00678                 error = M2MTLVDeserializer::deserialize_resources(
00679                             received_coap_header->payload_ptr,
00680                             received_coap_header->payload_len, *this,
00681                             M2MTLVDeserializer::Post);
00682 
00683                 uint16_t instance_id = M2MTLVDeserializer::instance_id(received_coap_header->payload_ptr);
00684                 switch(error) {
00685                     case M2MTLVDeserializer::None:
00686                         if(observation_handler) {
00687                             execute_value_updated = true;
00688                         }
00689                         coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
00690 
00691                         if (coap_response->options_list_ptr) {
00692 
00693                             StringBuffer<MAX_PATH_SIZE_3> obj_name;
00694                             if(!build_path(obj_name, _parent.name(), M2MBase::instance_id(), instance_id)) {
00695                                 msg_code = COAP_MSG_CODE_RESPONSE_INTERNAL_SERVER_ERROR;
00696                                 break;
00697                             }
00698 
00699                             coap_response->options_list_ptr->location_path_len = obj_name.get_size();
00700                             coap_response->options_list_ptr->location_path_ptr =
00701                               alloc_string_copy((uint8_t*)obj_name.c_str(),
00702                                                 coap_response->options_list_ptr->location_path_len);
00703                             // todo: handle allocation error
00704                         }
00705                         msg_code = COAP_MSG_CODE_RESPONSE_CREATED;
00706                         break;
00707                     case M2MTLVDeserializer::NotAllowed:
00708                         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00709                         break;
00710                     case M2MTLVDeserializer::NotValid:
00711                         msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST;
00712                         break;
00713                     case M2MTLVDeserializer::NotFound:
00714                         msg_code = COAP_MSG_CODE_RESPONSE_NOT_FOUND;
00715                         break;
00716                     case M2MTLVDeserializer::OutOfMemory:
00717                         msg_code = COAP_MSG_CODE_RESPONSE_REQUEST_ENTITY_TOO_LARGE;
00718                         break;
00719                     default:
00720                         break;
00721                 }
00722             } else {
00723                 msg_code =COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
00724             } // if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type)
00725         } else {
00726             // Operation is not allowed.
00727             tr_error("M2MObjectInstance::handle_post_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
00728             msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00729         }
00730     } else {
00731         msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
00732     }
00733     if(coap_response) {
00734         coap_response->msg_code = msg_code;
00735     }
00736     return coap_response;
00737 }
00738 
00739 void M2MObjectInstance::notification_update(M2MBase::Observation observation_level)
00740 {
00741     tr_debug("M2MObjectInstance::notification_update() - level(%d)", observation_level);
00742     if((M2MBase::O_Attribute & observation_level) == M2MBase::O_Attribute) {
00743         tr_debug("M2MObjectInstance::notification_update() - object callback");
00744         _parent.notification_update(instance_id());
00745     }
00746     if((M2MBase::OI_Attribute & observation_level) == M2MBase::OI_Attribute) {
00747         tr_debug("M2MObjectInstance::notification_update() - object instance callback");
00748         M2MReportHandler *report_handler = M2MBase::report_handler();
00749         if(report_handler && is_under_observation()) {
00750             report_handler->set_notification_trigger();
00751         }
00752 
00753     }
00754 }
00755 
00756 M2MBase::DataType M2MObjectInstance::convert_resource_type(M2MResourceInstance::ResourceType type)
00757 {
00758     M2MBase::DataType data_type = M2MBase::OBJLINK;
00759     switch(type) {
00760         case M2MResourceInstance::STRING:
00761             data_type = M2MBase::STRING;
00762             break;
00763         case M2MResourceInstance::INTEGER:
00764             data_type = M2MBase::INTEGER;
00765             break;
00766         case M2MResourceInstance::FLOAT:
00767             data_type = M2MBase::FLOAT;
00768             break;
00769         case M2MResourceInstance::OPAQUE:
00770             data_type = M2MBase::OPAQUE;
00771             break;
00772         case M2MResourceInstance::BOOLEAN:
00773             data_type = M2MBase::BOOLEAN;
00774             break;
00775         case M2MResourceInstance::TIME:
00776             data_type = M2MBase::TIME;
00777             break;
00778         case M2MResourceInstance::OBJLINK:
00779             data_type = M2MBase::OBJLINK;
00780             break;
00781     }
00782     return data_type;
00783 }