mbed client lightswitch demo

Dependencies:   mbed Socket lwip-eth lwip-sys lwip

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

Revision:
11:cada08fc8a70
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-client/source/m2minterfaceimpl.cpp	Thu Jun 09 17:08:36 2016 +0000
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 2015 ARM Limited. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ * Licensed under the Apache License, Version 2.0 (the License); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <assert.h>
+#include "include/m2minterfaceimpl.h"
+#include "include/eventdata.h"
+#include "mbed-client/m2minterfaceobserver.h"
+#include "mbed-client/m2mconnectionhandler.h"
+#include "mbed-client/m2mconnectionsecurity.h"
+#include "include/m2mnsdlinterface.h"
+#include "mbed-client/m2msecurity.h"
+#include "mbed-client/m2mconstants.h"
+#include "mbed-client/m2mtimer.h"
+#include "ns_trace.h"
+
+M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver& observer,
+                                   const String &ep_name,
+                                   const String &ep_type,
+                                   const int32_t l_time,
+                                   const uint16_t listen_port,
+                                   const String &dmn,
+                                   M2MInterface::BindingMode mode,
+                                   M2MInterface::NetworkStack stack,
+                                   const String &con_addr)
+: _observer(observer),
+  _nsdl_interface(new M2MNsdlInterface(*this)),
+  _current_state(0),
+  _max_states( STATE_MAX_STATES ),
+  _event_generated(false),
+  _event_data(NULL),
+  _endpoint_name(ep_name),
+  _endpoint_type(ep_type),
+  _domain( dmn),
+  _life_time(l_time),
+  _binding_mode(mode),
+  _context_address(con_addr),
+  _listen_port(listen_port),
+  _register_server(NULL),
+  _event_ignored(false),
+  _register_ongoing(false),
+  _update_register_ongoing(false),
+  _queue_sleep_timer(new M2MTimer(*this)),
+  _callback_handler(NULL)
+{
+    M2MConnectionSecurity::SecurityMode sec_mode = M2MConnectionSecurity::DTLS;
+    //Hack for now
+    if( _binding_mode == M2MInterface::TCP ){
+        _binding_mode = M2MInterface::UDP;
+        sec_mode = M2MConnectionSecurity::TLS;
+    }else if( _binding_mode == M2MInterface::TCP_QUEUE ){
+        _binding_mode = M2MInterface::UDP_QUEUE;
+        sec_mode = M2MConnectionSecurity::TLS;
+    }
+    tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -IN");
+    _nsdl_interface->create_endpoint(_endpoint_name,
+                                     _endpoint_type,
+                                     _life_time,
+                                     _domain,
+                                     (uint8_t)_binding_mode,
+                                     _context_address);
+
+    //Here we must use TCP still
+    _connection_handler = new M2MConnectionHandler(*this, new M2MConnectionSecurity(sec_mode), mode, stack);
+
+    _connection_handler->bind_connection(_listen_port);
+     tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -OUT");
+}
+
+
+M2MInterfaceImpl::~M2MInterfaceImpl()
+{
+    tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - IN");
+    delete _queue_sleep_timer;
+    delete _nsdl_interface;
+    _connection_handler->stop_listening();
+    delete _connection_handler;
+    tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - OUT");
+}
+
+void M2MInterfaceImpl::bootstrap(M2MSecurity *security)
+{
+    tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - IN");
+    // Transition to a new state based upon
+    // the current state of the state machine
+    M2MSecurityData* data = new M2MSecurityData();
+    data->_object = security;
+    BEGIN_TRANSITION_MAP                                    // - Current State -
+        TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP)              // state_idle
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_registered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_waiting
+    END_TRANSITION_MAP(data)
+    if(_event_ignored) {
+        _event_ignored = false;
+        _observer.error(M2MInterface::NotAllowed);
+    }
+    tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - OUT");
+}
+
+void M2MInterfaceImpl::cancel_bootstrap()
+{
+//TODO: Do we need this ?
+}
+
+void M2MInterfaceImpl::register_object(M2MSecurity *security, const M2MObjectList &object_list)
+{
+    tr_debug("M2MInterfaceImpl::register_object(M2MSecurity *security,const M2MObjectList &object_list) - IN");
+    // Transition to a new state based upon
+    // the current state of the state machine
+    //TODO: manage register object in a list.
+    if(!_register_ongoing) {
+       _register_ongoing = true;
+        _register_server = security;
+        M2MRegisterData *data = new M2MRegisterData();
+        data->_object = security;
+        data->_object_list = object_list;
+        BEGIN_TRANSITION_MAP                                    // - Current State -
+            TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_idle
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+            TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_bootstrapped
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
+            TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_registered
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+            TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_waiting
+        END_TRANSITION_MAP(data)
+        if(_event_ignored) {
+            _event_ignored = false;
+            _observer.error(M2MInterface::NotAllowed);
+        }
+    } else {
+       tr_debug("M2MInterfaceImpl::register_object(M2MSecurity *security,const M2MObjectList &object_list) - NOT ALLOWED");
+        _observer.error(M2MInterface::NotAllowed);
+    }
+    tr_debug("M2MInterfaceImpl::register_object(M2MSecurity *security,const M2MObjectList &object_list) - OUT");
+}
+
+void M2MInterfaceImpl::update_registration(M2MSecurity *security_object, const uint32_t lifetime)
+{
+    tr_debug("M2MInterfaceImpl::update_registration(M2MSecurity *security,const uint32_t lifetime) - IN");
+    // Transition to a new state based upon
+    // the current state of the state machine
+    if(lifetime != 0 && (lifetime < MINIMUM_REGISTRATION_TIME)) {
+        _observer.error(M2MInterface::InvalidParameters);
+    } else if(!_update_register_ongoing){
+        _update_register_ongoing = true;
+        M2MUpdateRegisterData *data = new M2MUpdateRegisterData();
+        data->_object = security_object;
+        data->_lifetime = lifetime;
+        BEGIN_TRANSITION_MAP                                    // - Current State -
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_idle
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
+            TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_registered
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+            TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+            TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_waiting
+        END_TRANSITION_MAP(data)
+        if(_event_ignored) {
+            _event_ignored = false;
+            _observer.error(M2MInterface::NotAllowed);
+        }
+    } else {
+        tr_debug("M2MInterfaceImpl::update_registration(M2MSecurity *security,const M2MObjectList &object_list) - NOT ALLOWED");
+        _observer.error(M2MInterface::NotAllowed);
+    }
+    tr_debug("M2MInterfaceImpl::update_registration(M2MSecurity *security,const uint32_t lifetime) - OUT");
+}
+
+void M2MInterfaceImpl::unregister_object(M2MSecurity* /*security*/)
+{
+    tr_debug("M2MInterfaceImpl::unregister_object(M2MSecurity *security) - IN");
+    // Transition to a new state based upon
+    // the current state of the state machine
+    BEGIN_TRANSITION_MAP                                // - Current State -
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_idle
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_registered
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_update_registration
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
+        TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
+        TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_waiting
+    END_TRANSITION_MAP(NULL)
+    if(_event_ignored) {
+        _event_ignored = false;
+        _observer.error(M2MInterface::NotAllowed);
+    }
+    tr_debug("M2MInterfaceImpl::unregister_object(M2MSecurity *security) - OUT");
+}
+
+void M2MInterfaceImpl::set_queue_sleep_handler(callback_handler handler)
+{
+    tr_debug("M2MInterfaceImpl::set_queue_sleep_handler()");
+    _callback_handler = handler;
+}
+
+void M2MInterfaceImpl::coap_message_ready(uint8_t *data_ptr,
+                                          uint16_t data_len,
+                                          sn_nsdl_addr_s *address_ptr)
+{
+    tr_debug("M2MInterfaceImpl::coap_message_ready(uint8_t *data_ptr,uint16_t data_len,sn_nsdl_addr_s *address_ptr)");
+    internal_event(STATE_SENDING_COAP_DATA);
+    if(!_connection_handler->send_data(data_ptr,data_len,address_ptr)) {
+        internal_event( STATE_IDLE);
+        tr_error("M2MInterfaceImpl::coap_message_ready() - M2MInterface::NetworkError");
+        _observer.error(M2MInterface::NetworkError);
+    }
+}
+
+void M2MInterfaceImpl::client_registered(M2MServer *server_object)
+{
+    tr_debug("M2MInterfaceImpl::client_registered(M2MServer *server_object)");
+    internal_event(STATE_REGISTERED);
+    //Inform client is registered.
+    //TODO: manage register object in a list.
+    _observer.object_registered(_register_server,*server_object);
+}
+
+void M2MInterfaceImpl::registration_updated(const M2MServer &server_object)
+{
+    tr_debug("M2MInterfaceImpl::registration_updated(const M2MServer &server_object)");
+    internal_event(STATE_REGISTERED);
+    _observer.registration_updated(_register_server,server_object);
+}
+
+
+void M2MInterfaceImpl::registration_error(uint8_t error_code)
+{
+    tr_debug("M2MInterfaceImpl::registration_error(uint8_t error_code) %d", error_code);
+    internal_event(STATE_IDLE);
+    _observer.error((M2MInterface::Error)error_code);
+}
+
+void M2MInterfaceImpl::client_unregistered()
+{
+    tr_debug("M2MInterfaceImpl::client_unregistered()");
+    internal_event(STATE_UNREGISTERED);
+    //TODO: manage register object in a list.
+    _observer.object_unregistered(_register_server);
+}
+
+void M2MInterfaceImpl::bootstrap_done(M2MSecurity *security_object)
+{
+    tr_debug("M2MInterfaceImpl::bootstrap_done(M2MSecurity *security_object)");
+    internal_event(STATE_BOOTSTRAPPED);
+    _observer.bootstrap_done(security_object);
+}
+
+void M2MInterfaceImpl::bootstrap_error()
+{
+    tr_debug("M2MInterfaceImpl::bootstrap_error()");
+    internal_event(STATE_IDLE);
+    _observer.error(M2MInterface::BootstrapFailed);
+}
+
+void M2MInterfaceImpl::coap_data_processed()
+{
+    tr_debug("M2MInterfaceImpl::coap_data_processed()");
+    internal_event(STATE_COAP_DATA_PROCESSED);
+}
+
+void M2MInterfaceImpl::value_updated(M2MBase *base)
+{
+    tr_debug("M2MInterfaceImpl::value_updated(M2MBase *base)");
+    if(base) {
+        M2MBase::BaseType type = base->base_type();
+        _observer.value_updated(base, type);
+    }
+}
+
+void M2MInterfaceImpl::data_available(uint8_t* data,
+                                      uint16_t data_size,
+                                      const M2MConnectionObserver::SocketAddress &address)
+{
+    tr_debug("M2MInterfaceImpl::data_available(uint8_t* data,uint16_t data_size,const M2MConnectionObserver::SocketAddress &address)");
+    ReceivedData *event = new ReceivedData();
+    event->_data = data;
+    event->_size = data_size;
+    event->_address = &address;
+    internal_event(STATE_COAP_DATA_RECEIVED, event);
+}
+
+void M2MInterfaceImpl::socket_error(uint8_t /*error_code*/)
+{
+    tr_debug("M2MInterfaceImpl::socket_error(uint8_t error_code)");
+    internal_event(STATE_IDLE);
+    M2MInterface::Error error = M2MInterface::NetworkError;
+    _observer.error(error);
+}
+
+void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &address,
+                                     M2MConnectionObserver::ServerType server_type,
+                                     const uint16_t server_port)
+{
+    tr_debug("M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress ,M2MConnectionObserver::ServerType,const uint16_t)");
+    ResolvedAddressData *data = new ResolvedAddressData();
+    data->_address = &address;
+    data->_port = server_port;
+    if( M2MConnectionObserver::Bootstrap == server_type) {
+        tr_debug("M2MInterfaceImpl::address_ready() Server Type Bootstrap");
+        internal_event(STATE_BOOTSTRAP_ADDRESS_RESOLVED, data);
+    } else {
+        tr_debug("M2MInterfaceImpl::address_ready() Server Type LWM2M");
+        internal_event(STATE_REGISTER_ADDRESS_RESOLVED, data);
+    }
+}
+
+void M2MInterfaceImpl::data_sent()
+{
+    tr_debug("M2MInterfaceImpl::data_sent()");
+    if(_binding_mode == M2MInterface::UDP_QUEUE ||
+       _binding_mode == M2MInterface::TCP_QUEUE  ||
+       _binding_mode == M2MInterface::SMS_QUEUE  ||
+       _binding_mode == M2MInterface::UDP_SMS_QUEUE) {
+        if(_callback_handler) {
+            _queue_sleep_timer->stop_timer();
+            _queue_sleep_timer->start_timer(RETRY_COUNT*RETRY_INTERVAL*1000, M2MTimerObserver::QueueSleep);
+        }
+    }
+    internal_event(STATE_COAP_DATA_SENT);
+}
+
+void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type)
+{
+    tr_debug("M2MInterfaceImpl::timer_expired()");
+    if(M2MTimerObserver::QueueSleep == type) {        
+        if(_callback_handler) {
+            _callback_handler();
+        }
+    _queue_sleep_timer->stop_timer();
+    }
+}
+
+// state machine sits here.
+void M2MInterfaceImpl::state_idle(EventData* /*data*/)
+{
+    // Handle Idle state here
+    // Cleanup all resources, if necessary
+    _connection_handler->stop_listening();
+    _nsdl_interface->stop_timers();
+    _register_ongoing = false;
+    _update_register_ongoing = false;
+    tr_debug("M2MInterfaceImpl::state_idle");
+}
+
+void M2MInterfaceImpl::state_bootstrap( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_bootstrap");
+    // Start with bootstrapping preparation
+    bool success = false;
+    if(data) {
+        M2MSecurityData *event = (M2MSecurityData *)data;
+        M2MSecurity *security = event->_object;
+        if(security) {
+            if(M2MSecurity::Bootstrap == security->server_type()) {
+                tr_debug("M2MInterfaceImpl::state_bootstrap - server_type : M2MSecurity::Bootstrap");
+                String server_address = security->resource_value_string(M2MSecurity::M2MServerUri);
+                tr_debug("M2MInterfaceImpl::state_bootstrap - server_address %s", server_address.c_str());
+                String ip_address;
+                uint16_t port;
+                if(server_address.compare(0,COAP.size(),COAP) == 0) {
+                    server_address = server_address.substr(COAP.size(),
+                                                           server_address.size()-COAP.size());
+                    int colonFound = server_address.find_last_of(':');
+                    if(colonFound != -1) {
+                       ip_address = server_address.substr(0,colonFound);
+                       port = atoi(server_address.substr(colonFound+1,
+                                                         server_address.size()-ip_address.size()).c_str());
+
+                        tr_debug("M2MInterfaceImpl::state_bootstrap - IP address %s , Port %d", ip_address.c_str(), port);
+                       // If bind and resolving server address succeed then proceed else
+                       // return error to the application and go to Idle state.
+                       if(_connection_handler->resolve_server_address(ip_address,
+                                                                      port,
+                                                                      M2MConnectionObserver::Bootstrap,
+                                                                      security)) {
+                           tr_debug("M2MInterfaceImpl::state_bootstrap - resolve_server_address - success");
+                           success = true;
+                       }
+                    }
+                }
+            }
+        }
+    }
+    if(!success) {
+        tr_error("M2MInterfaceImpl::state_bootstrap - M2MInterface::InvalidParameters");
+        _observer.error(M2MInterface::InvalidParameters);
+        internal_event(STATE_IDLE);
+    }
+}
+
+void M2MInterfaceImpl::state_bootstrap_address_resolved( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved");
+    ResolvedAddressData *event = (ResolvedAddressData *)data;
+    sn_nsdl_addr_s address;
+
+    M2MInterface::NetworkStack stack = event->_address->_stack;
+
+    if(M2MInterface::LwIP_IPv4 == stack) {
+        tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv4 address");
+        address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
+        address.addr_len = 4;
+    } else if((M2MInterface::LwIP_IPv6 == stack) ||
+              (M2MInterface::Nanostack_IPv6 == stack)) {
+        tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv6 address");
+        address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
+        address.addr_len = 16;
+    }
+    address.port = event->_port;
+    address.addr_ptr = (uint8_t*)event->_address->_address;
+    _connection_handler->start_listening_for_data();
+    if(_nsdl_interface->create_bootstrap_resource(&address)) {
+       tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : create_bootstrap_resource - success");
+       internal_event(STATE_BOOTSTRAP_RESOURCE_CREATED);
+    } else{
+        // If resource creation fails then inform error to application
+        tr_error("M2MInterfaceImpl::state_bootstrap_address_resolved : M2MInterface::InvalidParameters");
+        internal_event(STATE_IDLE);
+        _observer.error(M2MInterface::InvalidParameters);
+    }
+}
+
+void M2MInterfaceImpl::state_bootstrap_resource_created( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_bootstrap_resource_created");
+}
+
+void M2MInterfaceImpl::state_bootstrapped( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_bootstrapped");
+}
+
+void M2MInterfaceImpl::state_register( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_register");
+    // Start with registration preparation
+    bool success = false;
+    M2MInterface::Error error = M2MInterface::InvalidParameters;
+    if(data) {
+        M2MRegisterData *event = (M2MRegisterData *)data;
+        M2MSecurity *security = event->_object;
+        if(security) {
+            if(M2MSecurity::M2MServer == security->server_type()) {
+                tr_debug("M2MInterfaceImpl::state_register - server_type : M2MSecurity::M2MServer");
+                if(_nsdl_interface->create_nsdl_list_structure(event->_object_list)) {
+                    tr_debug("M2MInterfaceImpl::state_register - create_nsdl_list_structure - success");
+                    // If the nsdl resource structure is created successfully
+                    String server_address = security->resource_value_string(M2MSecurity::M2MServerUri);
+                    tr_debug("M2MInterfaceImpl::state_register - server_address %s", server_address.c_str());
+                    String ip_address;
+                    uint16_t port;
+                    if(server_address.compare(0,COAP.size(),COAP) == 0) {
+                        server_address = server_address.substr(COAP.size(),
+                                                               server_address.size()-COAP.size());
+                        int colonFound = server_address.find_last_of(':'); //10
+                        if(colonFound != -1) {
+                           ip_address = server_address.substr(0,colonFound);
+                           port = atoi(server_address.substr(colonFound+1,
+                                                             server_address.size()-ip_address.size()).c_str());
+
+                            tr_debug("M2MInterfaceImpl::state_register - IP address %s , Port %d", ip_address.c_str(), port);
+                           // If bind and resolving server address succeed then proceed else
+                           // return error to the application and go to Idle state.
+                           if(_connection_handler->resolve_server_address(ip_address,
+                                                                          port,
+                                                                          M2MConnectionObserver::LWM2MServer,
+                                                                          security)) {
+                                tr_debug("M2MInterfaceImpl::state_register - resolve_server_address - success");
+                                success = true;
+                            } else {
+                                tr_error("M2MInterfaceImpl::state_register - set error as M2MInterface::NetworkError");
+                                error = M2MInterface::NetworkError;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    if(!success) {
+        tr_error("M2MInterfaceImpl::state_register - Error Occured %d", (int)error);
+        internal_event(STATE_IDLE);
+        _observer.error(error);
+    }
+}
+
+void M2MInterfaceImpl::state_register_address_resolved( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_register_address_resolved");
+    if(data) {
+        ResolvedAddressData *event = (ResolvedAddressData *)data;
+
+        sn_nsdl_addr_type_e address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
+
+        M2MInterface::NetworkStack stack = event->_address->_stack;
+
+        if(M2MInterface::LwIP_IPv4 == stack) {
+            tr_debug("M2MInterfaceImpl::state_register_address_resolved : IPv4 address");
+            address_type = SN_NSDL_ADDRESS_TYPE_IPV4;
+        } else if((M2MInterface::LwIP_IPv6 == stack) ||
+                  (M2MInterface::Nanostack_IPv6 == stack)) {
+            tr_debug("M2MInterfaceImpl::state_register_address_resolved : IPv6 address");
+            address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
+        }
+        internal_event(STATE_REGISTER_RESOURCE_CREATED);
+        _connection_handler->start_listening_for_data();
+        if(!_nsdl_interface->send_register_message((uint8_t*)event->_address->_address,event->_port, address_type)) {
+            // If resource creation fails then inform error to application
+            tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::InvalidParameters");
+            internal_event(STATE_IDLE);
+            _observer.error(M2MInterface::InvalidParameters);
+        }
+    }
+}
+
+void M2MInterfaceImpl::state_register_resource_created( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_register_resource_created");
+}
+
+void M2MInterfaceImpl::state_registered( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_registered");
+    _register_ongoing = false;
+    _update_register_ongoing = false;
+}
+
+void M2MInterfaceImpl::state_update_registration( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_update_registration");
+    // Start with registration preparation
+    bool success = false;
+    if(data) {
+        M2MUpdateRegisterData *event = (M2MUpdateRegisterData *)data;
+        success = _nsdl_interface->send_update_registration(event->_lifetime);
+
+    }
+    if(!success) {
+        tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::InvalidParameters");
+        internal_event(STATE_IDLE);
+        _observer.error(M2MInterface::InvalidParameters);
+    }
+}
+
+void M2MInterfaceImpl::state_unregister( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_unregister");
+    internal_event(STATE_SENDING_COAP_DATA);
+    if(!_nsdl_interface->send_unregister_message()) {
+        tr_error("M2MInterfaceImpl::state_unregister : M2MInterface::NotRegistered");
+        internal_event(STATE_IDLE);
+        _observer.error(M2MInterface::NotRegistered);
+    }
+}
+
+void M2MInterfaceImpl::state_unregistered( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_unregistered");
+    internal_event(STATE_IDLE);
+}
+
+void M2MInterfaceImpl::state_sending_coap_data( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_sending_coap_data");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_coap_data_sent( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_coap_data_sent");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_coap_data_received( EventData *data)
+{
+    tr_debug("M2MInterfaceImpl::state_coap_data_received");
+    if(data) {
+        ReceivedData *event = (ReceivedData*)data;
+        sn_nsdl_addr_s address;
+
+        M2MInterface::NetworkStack stack = event->_address->_stack;
+
+        if(M2MInterface::LwIP_IPv4 == stack) {
+            tr_debug("M2MInterfaceImpl::state_coap_data_received : IPv4 address");
+            address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
+            address.addr_len = 4;
+        } else if((M2MInterface::LwIP_IPv6 == stack) ||
+                  (M2MInterface::Nanostack_IPv6 == stack)) {
+            tr_debug("M2MInterfaceImpl::state_coap_data_received : IPv6 address");
+            address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
+            address.addr_len = 16;
+        }
+        address.port = event->_address->_port;
+        address.addr_ptr = (uint8_t*)event->_address->_address;
+
+        // Process received data
+        internal_event(STATE_PROCESSING_COAP_DATA);
+        if(!_nsdl_interface->process_received_data(event->_data,
+                                                  event->_size,
+                                                  &address)) {
+           tr_error("M2MInterfaceImpl::state_coap_data_received : M2MInterface::ResponseParseFailed");
+            _observer.error(M2MInterface::ResponseParseFailed);
+        }
+    }
+}
+
+void M2MInterfaceImpl::state_processing_coap_data( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_processing_coap_data");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_coap_data_processed( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_coap_data_processed");
+    internal_event(STATE_WAITING);
+}
+
+void M2MInterfaceImpl::state_waiting( EventData */*data*/)
+{
+    tr_debug("M2MInterfaceImpl::state_waiting");
+}
+
+// generates an external event. called once per external event
+// to start the state machine executing
+void M2MInterfaceImpl::external_event(uint8_t new_state,
+                                     EventData* p_data)
+{
+    tr_debug("M2MInterfaceImpl::external_event : new state %d", new_state);
+    // if we are supposed to ignore this event
+    if (new_state == EVENT_IGNORED) {
+        tr_debug("M2MInterfaceImpl::external_event : new state is EVENT_IGNORED");
+        // just delete the event data, if any
+        if (p_data) {
+            delete p_data;
+            p_data = NULL;
+        }
+        _event_ignored = true;
+    }
+    else {
+        tr_debug("M2MInterfaceImpl::external_event : handle new state");
+        // generate the event and execute the state engine
+        internal_event(new_state, p_data);
+    }
+}
+
+// generates an internal event. called from within a state
+// function to transition to a new state
+void M2MInterfaceImpl::internal_event(uint8_t new_state,
+                                      EventData* p_data)
+{
+    tr_debug("M2MInterfaceImpl::internal_event : new state %d", new_state);
+    _event_data = p_data;
+    _event_generated = true;
+    _current_state = new_state;
+    state_engine();
+}
+
+// the state engine executes the state machine states
+void M2MInterfaceImpl::state_engine (void )
+{
+    tr_debug("M2MInterfaceImpl::state_engine");
+    EventData* p_data_temp = NULL;
+
+    // while events are being generated keep executing states
+    while (_event_generated) {
+        p_data_temp = _event_data;  // copy of event data pointer
+        _event_data = NULL;       // event data used up, reset ptr
+        _event_generated = false;  // event used up, reset flag
+
+        assert(_current_state < _max_states);
+
+        state_function( _current_state, p_data_temp );
+
+        // if event data was used, then delete it
+        if (p_data_temp) {
+            delete p_data_temp;
+            p_data_temp = NULL;
+        }
+    }
+}
+
+void M2MInterfaceImpl::state_function( uint8_t current_state, EventData* data )
+{
+    switch( current_state ) {
+    case STATE_IDLE:
+            M2MInterfaceImpl::state_idle(data);
+            break;
+        case STATE_BOOTSTRAP:
+            M2MInterfaceImpl::state_bootstrap(data);
+            break;
+        case STATE_BOOTSTRAP_ADDRESS_RESOLVED:
+            M2MInterfaceImpl::state_bootstrap_address_resolved(data);
+            break;
+        case STATE_BOOTSTRAP_RESOURCE_CREATED:
+            M2MInterfaceImpl::state_bootstrap_resource_created(data);
+            break;
+        case STATE_BOOTSTRAPPED:
+            M2MInterfaceImpl::state_bootstrapped(data);
+            break;
+        case STATE_REGISTER:
+            M2MInterfaceImpl::state_register(data);
+            break;
+        case STATE_REGISTER_ADDRESS_RESOLVED:
+            M2MInterfaceImpl::state_register_address_resolved(data);
+            break;
+        case STATE_REGISTER_RESOURCE_CREATED:
+            M2MInterfaceImpl::state_register_resource_created(data);
+            break;
+        case STATE_REGISTERED:
+            M2MInterfaceImpl::state_registered(data);
+            break;
+        case STATE_UPDATE_REGISTRATION:
+            M2MInterfaceImpl::state_update_registration(data);
+            break;
+        case STATE_UNREGISTER:
+            M2MInterfaceImpl::state_unregister(data);
+            break;
+        case STATE_UNREGISTERED:
+            M2MInterfaceImpl::state_unregistered(data);
+            break;
+        case STATE_SENDING_COAP_DATA:
+            M2MInterfaceImpl::state_sending_coap_data(data);
+            break;
+        case STATE_COAP_DATA_SENT:
+            M2MInterfaceImpl::state_coap_data_sent(data);
+            break;
+        case STATE_COAP_DATA_RECEIVED:
+            M2MInterfaceImpl::state_coap_data_received(data);
+            break;
+        case STATE_PROCESSING_COAP_DATA:
+            M2MInterfaceImpl::state_processing_coap_data(data);
+            break;
+        case STATE_COAP_DATA_PROCESSED:
+            M2MInterfaceImpl::state_coap_data_processed(data);
+            break;
+        case STATE_WAITING:
+            M2MInterfaceImpl::state_waiting(data);
+            break;
+    }
+}