mbed client lightswitch demo

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

Fork of mbed-client-classic-example-lwip by Austin Blackstone

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