joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2minterfaceimpl.cpp Source File

m2minterfaceimpl.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 <assert.h>
00017 #include "include/m2minterfaceimpl.h"
00018 #include "include/eventdata.h"
00019 #include "mbed-client/m2minterfaceobserver.h"
00020 #include "mbed-client/m2mconnectionhandler.h"
00021 #include "mbed-client/m2mconnectionsecurity.h"
00022 #include "include/m2mnsdlinterface.h"
00023 #include "include/nsdlaccesshelper.h"
00024 #include "mbed-client/m2msecurity.h"
00025 #include "mbed-client/m2mconstants.h"
00026 #include "mbed-client/m2mtimer.h"
00027 #include "mbed-trace/mbed_trace.h"
00028 
00029 #define TRACE_GROUP "mClt"
00030 
00031 M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver& observer,
00032                                    const String &ep_name,
00033                                    const String &ep_type,
00034                                    const int32_t l_time,
00035                                    const uint16_t listen_port,
00036                                    const String &dmn,
00037                                    M2MInterface::BindingMode mode,
00038                                    M2MInterface::NetworkStack stack,
00039                                    const String &con_addr)
00040 : _observer(observer),
00041   _nsdl_interface(new M2MNsdlInterface(*this)),
00042   _current_state(0),
00043   _max_states( STATE_MAX_STATES ),
00044   _event_generated(false),
00045   _event_data(NULL),
00046   _endpoint_type(ep_type),
00047   _domain( dmn),
00048   _life_time(l_time),
00049   _binding_mode(mode),
00050   _context_address(con_addr),
00051   _listen_port(listen_port),
00052   _server_port(0),
00053   _register_server(NULL),
00054   _event_ignored(false),
00055   _register_ongoing(false),
00056   _update_register_ongoing(false),
00057   _queue_sleep_timer(new M2MTimer(*this)),
00058   _retry_timer(new M2MTimer(*this)),
00059   _bootstrap_timer(NULL),
00060   _callback_handler(NULL),
00061   _security(NULL),
00062   _retry_count(0),
00063   _reconnecting(false),
00064   _retry_timer_expired(false)
00065 {
00066     M2MConnectionSecurity::SecurityMode sec_mode = M2MConnectionSecurity::DTLS;
00067     //Hack for now
00068     if( _binding_mode == M2MInterface::TCP ){
00069         _binding_mode = M2MInterface::UDP;
00070         sec_mode = M2MConnectionSecurity::TLS;
00071     }else if( _binding_mode == M2MInterface::TCP_QUEUE ){
00072         _binding_mode = M2MInterface::UDP_QUEUE;
00073         sec_mode = M2MConnectionSecurity::TLS;
00074     }
00075     tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -IN");
00076     _nsdl_interface->create_endpoint(ep_name,
00077                                      _endpoint_type,
00078                                      _life_time,
00079                                      _domain,
00080                                      (uint8_t)_binding_mode,
00081                                      _context_address);
00082 
00083     //Doesn't own, ownership is passed to ConnectionHandler class
00084     _security_connection = new M2MConnectionSecurity(sec_mode);
00085     //Here we must use TCP still
00086     _connection_handler = new M2MConnectionHandler(*this, _security_connection, mode, stack);
00087     __connection_handler = _connection_handler;
00088     _connection_handler->bind_connection(_listen_port);
00089 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00090     _bootstrap_timer = new M2MTimer(*this);
00091 #endif
00092     tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -OUT");
00093 }
00094 
00095 
00096 M2MInterfaceImpl::~M2MInterfaceImpl()
00097 {
00098     tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - IN");
00099     delete _queue_sleep_timer;
00100     delete _nsdl_interface;
00101     _connection_handler->stop_listening();
00102     __connection_handler = NULL;
00103     delete _connection_handler;
00104     delete _retry_timer;
00105     delete _bootstrap_timer;
00106     _security_connection = NULL;
00107     tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - OUT");
00108 }
00109 
00110 void M2MInterfaceImpl::bootstrap(M2MSecurity *security)
00111 {
00112 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00113     tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - IN");
00114     // Transition to a new state based upon
00115     // the current state of the state machine
00116     M2MSecurityData* data = new M2MSecurityData();
00117     data->_object = security;
00118     BEGIN_TRANSITION_MAP                                    // - Current State -
00119         TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP)              // state_idle
00120         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00121         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00122         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00123         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
00124         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00125         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00126         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
00127         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_registered
00128         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
00129         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00130         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00131         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
00132         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
00133         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
00134         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
00135         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
00136         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_waiting
00137     END_TRANSITION_MAP(data)
00138     if(_event_ignored) {
00139         _event_ignored = false;
00140         _observer.error(M2MInterface::NotAllowed);
00141     }
00142     tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - OUT");
00143 #else
00144     _observer.error(M2MInterface::NotAllowed);
00145 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00146 }
00147 
00148 void M2MInterfaceImpl::cancel_bootstrap()
00149 {
00150 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00151 //TODO: Do we need this ?
00152 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00153 }
00154 
00155 void M2MInterfaceImpl::register_object(M2MSecurity *security, const M2MObjectList &object_list)
00156 {
00157     tr_debug("M2MInterfaceImpl::register_object - IN");
00158     // Transition to a new state based upon
00159     // the current state of the state machine
00160     //TODO: manage register object in a list.
00161     if(!_register_ongoing) {
00162        _register_ongoing = true;
00163         _register_server = security;
00164         M2MRegisterData *data = new M2MRegisterData();
00165         data->_object = security;
00166         data->_object_list = object_list;
00167         BEGIN_TRANSITION_MAP                                    // - Current State -
00168             TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_idle
00169             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00170             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00171             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00172             TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_bootstrapped
00173             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00174             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00175             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
00176             TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_registered
00177             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
00178             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00179             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00180             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
00181             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
00182             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
00183             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
00184             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
00185             TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_waiting
00186         END_TRANSITION_MAP(data)
00187         if(_event_ignored) {
00188             _event_ignored = false;
00189             _observer.error(M2MInterface::NotAllowed);
00190         }
00191     } else {
00192         tr_debug("M2MInterfaceImpl::register_object - NOT ALLOWED");
00193         _observer.error(M2MInterface::NotAllowed);
00194     }
00195     tr_debug("M2MInterfaceImpl::register_object - OUT");
00196 }
00197 
00198 void M2MInterfaceImpl::update_registration(M2MSecurity *security_object, const uint32_t lifetime)
00199 {
00200     tr_debug("M2MInterfaceImpl::update_registration - IN");
00201     // Transition to a new state based upon
00202     // the current state of the state machine
00203     if(lifetime != 0 && (lifetime < MINIMUM_REGISTRATION_TIME)) {
00204         _observer.error(M2MInterface::InvalidParameters);
00205     } else if(!_update_register_ongoing){
00206         tr_debug("M2MInterfaceImpl::update_registration - already ongoing");
00207         _update_register_ongoing = true;
00208         M2MUpdateRegisterData *data = new M2MUpdateRegisterData();
00209         data->_object = security_object;
00210         data->_lifetime = lifetime;
00211         BEGIN_TRANSITION_MAP                                    // - Current State -
00212             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_idle
00213             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00214             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00215             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00216             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
00217             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00218             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00219             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
00220             TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_registered
00221             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
00222             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00223             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00224             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
00225             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
00226             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
00227             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
00228             TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
00229             TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_waiting
00230         END_TRANSITION_MAP(data)
00231         if(_event_ignored) {
00232             _event_ignored = false;
00233             if (!_reconnecting)
00234                 _observer.error(M2MInterface::NotAllowed);
00235         }
00236     } else if(!_reconnecting) {
00237         tr_debug("M2MInterfaceImpl::update_registration - NOT ALLOWED");
00238         _observer.error(M2MInterface::NotAllowed);
00239     } else {
00240         tr_debug("M2MInterfaceImpl::update_registration - reconnecting");
00241     }
00242     tr_debug("M2MInterfaceImpl::update_registration - OUT");
00243 }
00244 
00245 void M2MInterfaceImpl::unregister_object(M2MSecurity* /*security*/)
00246 {
00247     tr_debug("M2MInterfaceImpl::unregister_object - IN");
00248     // Transition to a new state based upon
00249     // the current state of the state machine
00250     BEGIN_TRANSITION_MAP                                // - Current State -
00251         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_idle
00252         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00253         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00254         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00255         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
00256         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00257         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00258         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_resource_created
00259         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_registered
00260         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_update_registration
00261         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00262         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00263         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
00264         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
00265         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
00266         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
00267         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
00268         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_waiting
00269     END_TRANSITION_MAP(NULL)
00270     if(_event_ignored) {
00271         _event_ignored = false;
00272         _observer.error(M2MInterface::NotAllowed);
00273     }
00274     tr_debug("M2MInterfaceImpl::unregister_object - OUT");
00275 }
00276 
00277 void M2MInterfaceImpl::set_queue_sleep_handler(callback_handler handler)
00278 {
00279     tr_debug("M2MInterfaceImpl::set_queue_sleep_handler()");
00280     _callback_handler = handler;
00281 }
00282 
00283 void M2MInterfaceImpl::set_random_number_callback(random_number_cb callback)
00284 {
00285     if(_security_connection) {
00286         _security_connection->set_random_number_callback(callback);
00287     }
00288 }
00289 
00290 void M2MInterfaceImpl::set_entropy_callback(entropy_cb callback)
00291 {
00292     if(_security_connection) {
00293         _security_connection->set_entropy_callback(callback);
00294     }
00295 }
00296 
00297 void M2MInterfaceImpl::set_platform_network_handler(void *handler)
00298 {
00299     tr_debug("M2MInterfaceImpl::set_platform_network_handler()");
00300     if(_connection_handler) {
00301         _connection_handler->set_platform_network_handler(handler);
00302     }
00303 }
00304 
00305 void M2MInterfaceImpl::coap_message_ready(uint8_t *data_ptr,
00306                                           uint16_t data_len,
00307                                           sn_nsdl_addr_s *address_ptr)
00308 {
00309     tr_debug("M2MInterfaceImpl::coap_message_ready");
00310     internal_event(STATE_SENDING_COAP_DATA);
00311     if(!_connection_handler->send_data(data_ptr,data_len,address_ptr)) {
00312         internal_event( STATE_IDLE);
00313         tr_error("M2MInterfaceImpl::coap_message_ready() - M2MInterface::NetworkError");
00314         if (!_reconnecting) {
00315             _observer.error(M2MInterface::NetworkError);
00316         }
00317     }
00318 }
00319 
00320 void M2MInterfaceImpl::client_registered(M2MServer *server_object)
00321 {
00322     tr_debug("M2MInterfaceImpl::client_registered");
00323     _retry_count = 0;
00324     internal_event(STATE_REGISTERED);
00325     //Inform client is registered.
00326     //TODO: manage register object in a list.
00327     _observer.object_registered(_register_server,*server_object);
00328 }
00329 
00330 void M2MInterfaceImpl::registration_updated(const M2MServer &server_object)
00331 {
00332     tr_debug("M2MInterfaceImpl::registration_updated");
00333     internal_event(STATE_REGISTERED);
00334     _observer.registration_updated(_register_server,server_object);
00335 }
00336 
00337 void M2MInterfaceImpl::registration_error(uint8_t error_code, bool retry)
00338 {
00339     tr_debug("M2MInterfaceImpl::registration_error code [%d]", error_code);
00340     // Try to register again
00341     if (retry) {
00342         socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR);
00343     } else {
00344         internal_event(STATE_IDLE);
00345         _observer.error((M2MInterface::Error)error_code);
00346     }
00347 }
00348 
00349 void M2MInterfaceImpl::client_unregistered()
00350 {
00351     tr_debug("M2MInterfaceImpl::client_unregistered()");
00352     internal_event(STATE_UNREGISTERED);
00353     //TODO: manage register object in a list.
00354     _observer.object_unregistered(_register_server);
00355 }
00356 
00357 void M2MInterfaceImpl::bootstrap_done(M2MSecurity *security_object)
00358 {
00359 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00360     tr_debug("M2MInterfaceImpl::bootstrap_done");
00361     _bootstrap_timer->stop_timer();
00362     internal_event(STATE_BOOTSTRAPPED);
00363     _observer.bootstrap_done(security_object);
00364 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00365 }
00366 
00367 void M2MInterfaceImpl::bootstrap_error()
00368 {
00369 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00370     tr_debug("M2MInterfaceImpl::bootstrap_error()");
00371     _bootstrap_timer->stop_timer();
00372     internal_event(STATE_IDLE);
00373     _observer.error(M2MInterface::BootstrapFailed);
00374 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00375 }
00376 
00377 void M2MInterfaceImpl::coap_data_processed()
00378 {
00379     tr_debug("M2MInterfaceImpl::coap_data_processed()");
00380     internal_event(STATE_COAP_DATA_PROCESSED);
00381 }
00382 
00383 void M2MInterfaceImpl::value_updated(M2MBase *base)
00384 {
00385     tr_debug("M2MInterfaceImpl::value_updated(M2MBase *base)");
00386     if(base) {
00387         M2MBase::BaseType type = base->base_type();
00388         _observer.value_updated(base, type);
00389     }
00390 }
00391 
00392 void M2MInterfaceImpl::data_available(uint8_t* data,
00393                                       uint16_t data_size,
00394                                       const M2MConnectionObserver::SocketAddress &address)
00395 {
00396     tr_debug("M2MInterfaceImpl::data_available");
00397     ReceivedData *event = new ReceivedData();
00398     event->_data = data;
00399     event->_size = data_size;
00400     event->_address = &address;
00401     internal_event(STATE_COAP_DATA_RECEIVED, event);
00402 }
00403 
00404 void M2MInterfaceImpl::socket_error(uint8_t error_code, bool retry)
00405 {
00406     tr_debug("M2MInterfaceImpl::socket_error: (%d), retry (%d), reconnecting (%d)", error_code, retry, _reconnecting);
00407     if (!_retry_timer_expired && _reconnecting) {
00408         tr_debug("M2MInterfaceImpl::socket_error - retry timer running - return");
00409         return;
00410     }
00411     M2MInterface::Error error = M2MInterface::ErrorNone;
00412     switch (error_code) {
00413     case M2MConnectionHandler::SSL_CONNECTION_ERROR:
00414         error = M2MInterface::SecureConnectionFailed;
00415         break;
00416     case M2MConnectionHandler::DNS_RESOLVING_ERROR:
00417         error = M2MInterface::DnsResolvingFailed;
00418         break;
00419     case M2MConnectionHandler::SOCKET_READ_ERROR:
00420         error = M2MInterface::NetworkError;
00421         break;
00422     case M2MConnectionHandler::SOCKET_SEND_ERROR:
00423         error = M2MInterface::NetworkError;
00424         break;
00425     case M2MConnectionHandler::SSL_HANDSHAKE_ERROR:
00426         error = M2MInterface::SecureConnectionFailed;
00427         break;
00428     case M2MConnectionHandler::SOCKET_ABORT:
00429         error = M2MInterface::NetworkError;
00430         break;
00431     default:
00432         break;
00433     }
00434 
00435     // Try to do reconnecting
00436     if (retry) {
00437         if (_retry_count < MBED_CLIENT_RECONNECTION_COUNT) {
00438             internal_event(STATE_IDLE);
00439             _reconnecting = true;
00440             _retry_count++;
00441             _connection_handler->stop_listening();
00442             int retry_time = MBED_CLIENT_RECONNECTION_INTERVAL *
00443                     MBED_CLIENT_RECONNECTION_COUNT * _retry_count * 1000;
00444             _retry_timer_expired = false;
00445             _retry_timer->start_timer(retry_time,
00446                                       M2MTimerObserver::RetryTimer);
00447             tr_debug("M2MInterfaceImpl::socket_error - reconnecting in %d(s), count %d/%d", retry_time / 1000,
00448                      _retry_count, MBED_CLIENT_RECONNECTION_COUNT);
00449         } else {
00450             tr_debug("M2MInterfaceImpl::socket_error - no more retries");
00451             _connection_handler->stop_listening();
00452             _retry_timer->stop_timer();
00453             retry = false;
00454         }
00455     }
00456     // Inform application
00457     if (!retry && M2MInterface::ErrorNone != error) {
00458         tr_debug("M2MInterfaceImpl::socket_error - send error to application");
00459         _connection_handler->stop_listening();
00460         _retry_timer->stop_timer();
00461         _retry_count = 0;
00462         _reconnecting = false;
00463         _observer.error(error);
00464         internal_event(STATE_IDLE);
00465     }
00466 }
00467 
00468 void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &address,
00469                                      M2MConnectionObserver::ServerType server_type,
00470                                      const uint16_t server_port)
00471 {
00472     tr_debug("M2MInterfaceImpl::address_ready");
00473     ResolvedAddressData *data = new ResolvedAddressData();
00474     data->_address = &address;
00475     data->_port = server_port;
00476     if( M2MConnectionObserver::Bootstrap == server_type) {
00477         tr_debug("M2MInterfaceImpl::address_ready() Server Type Bootstrap");
00478         internal_event(STATE_BOOTSTRAP_ADDRESS_RESOLVED, data);
00479     } else {
00480         tr_debug("M2MInterfaceImpl::address_ready() Server Type LWM2M");
00481         internal_event(STATE_REGISTER_ADDRESS_RESOLVED, data);
00482     }
00483 }
00484 
00485 void M2MInterfaceImpl::data_sent()
00486 {
00487     tr_debug("M2MInterfaceImpl::data_sent()");
00488     if(_binding_mode == M2MInterface::UDP_QUEUE ||
00489        _binding_mode == M2MInterface::TCP_QUEUE  ||
00490        _binding_mode == M2MInterface::SMS_QUEUE  ||
00491        _binding_mode == M2MInterface::UDP_SMS_QUEUE) {
00492         if(_callback_handler) {
00493             _queue_sleep_timer->stop_timer();
00494             _queue_sleep_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT*MBED_CLIENT_RECONNECTION_INTERVAL*1000,
00495                                             M2MTimerObserver::QueueSleep);
00496         }
00497     }
00498     internal_event(STATE_COAP_DATA_SENT);
00499 }
00500 
00501 void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type)
00502 {
00503     tr_debug("M2MInterfaceImpl::timer_expired()");
00504     if(M2MTimerObserver::QueueSleep == type) {
00505         if(_callback_handler) {
00506             _callback_handler();
00507         }
00508     }
00509     else if (M2MTimerObserver::RetryTimer == type) {
00510         _retry_timer_expired = true;
00511         _listen_port = rand() % 64511 + 1024;
00512         tr_debug("M2MInterfaceImpl::timer_expired() - new port: %d", _listen_port);
00513         _connection_handler->bind_connection(_listen_port);
00514         internal_event(STATE_REGISTER);
00515     }
00516     else if (M2MTimerObserver::BootstrapTimer == type) {
00517         bootstrap_error();
00518     }
00519 }
00520 
00521 // state machine sits here.
00522 void M2MInterfaceImpl::state_idle(EventData* /*data*/)
00523 {
00524     tr_debug("M2MInterfaceImpl::state_idle");
00525     _nsdl_interface->stop_timers();
00526     _register_ongoing = false;
00527     _update_register_ongoing = false;
00528 }
00529 
00530 void M2MInterfaceImpl::state_bootstrap( EventData *data)
00531 {
00532 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00533     tr_debug("M2MInterfaceImpl::state_bootstrap");
00534     // Start with bootstrapping preparation
00535     bool success = false;
00536     if(data) {
00537         M2MSecurityData *event = static_cast<M2MSecurityData *> (data);
00538         M2MSecurity *security = event->_object;
00539         if(security) {
00540             if(M2MSecurity::Bootstrap == security->server_type()) {
00541                 tr_debug("M2MInterfaceImpl::state_bootstrap - server_type : M2MSecurity::Bootstrap");
00542                 String server_address = security->resource_value_string(M2MSecurity::M2MServerUri);
00543                 tr_debug("M2MInterfaceImpl::state_bootstrap - server_address %s", server_address.c_str());
00544                 _bootstrap_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00545                                               M2MTimerObserver::BootstrapTimer);
00546                 String ip_address;
00547                 String  coap;
00548                 if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
00549                      coap = COAP;
00550                 }
00551                 else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
00552                     security->resource_value_int(M2MSecurity::SecurityMode) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
00553                 }
00554                 if(!coap.empty()) {
00555                     server_address = server_address.substr(coap.size(),
00556                                                        server_address.size()-coap.size());
00557 
00558                     process_address(server_address, ip_address, _server_port);
00559 
00560                     tr_debug("M2MInterfaceImpl::state_bootstrap - IP address %s , Port %d", ip_address.c_str(), _server_port);
00561                     // If bind and resolving server address succeed then proceed else
00562                     // return error to the application and go to Idle state.
00563                     if(ip_address.empty()) {
00564                         tr_error("M2MInterfaceImpl::state_bootstrap - set error as M2MInterface::InvalidParameters");
00565                         success = false;
00566                     } else if(_connection_handler->resolve_server_address(ip_address,
00567                                                                   _server_port,
00568                                                                   M2MConnectionObserver::Bootstrap,
00569                                                                   security)) {
00570                        tr_debug("M2MInterfaceImpl::state_bootstrap - resolve_server_address - success");
00571                        success = true;
00572                    }
00573                 }
00574             }
00575         }
00576     }
00577     if(!success) {
00578         tr_error("M2MInterfaceImpl::state_bootstrap - M2MInterface::InvalidParameters");
00579         _observer.error(M2MInterface::InvalidParameters);
00580         internal_event(STATE_IDLE);
00581     }
00582 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00583 }
00584 
00585 void M2MInterfaceImpl::state_bootstrap_address_resolved( EventData *data)
00586 {
00587 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00588     tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved");
00589     ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
00590     sn_nsdl_addr_s address;
00591 
00592     M2MInterface::NetworkStack stack = event->_address->_stack;
00593 
00594     if(M2MInterface::LwIP_IPv4 == stack) {
00595         tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv4 address");
00596         address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
00597         address.addr_len = 4;
00598     } else if((M2MInterface::LwIP_IPv6 == stack) ||
00599               (M2MInterface::Nanostack_IPv6 == stack)) {
00600         tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv6 address");
00601         address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
00602         address.addr_len = 16;
00603     }
00604     address.port = event->_port;
00605     address.addr_ptr = (uint8_t*)event->_address->_address;
00606     address.addr_len = event->_address->_length;
00607     _connection_handler->start_listening_for_data();
00608 
00609     // Include domain id to be part of endpoint name
00610     String new_ep_name;
00611     new_ep_name += _nsdl_interface->endpoint_name();
00612     if (!_domain.empty()) {
00613         new_ep_name += '@';
00614         new_ep_name += _domain;
00615     }
00616     if(_nsdl_interface->create_bootstrap_resource(&address, new_ep_name)) {
00617        tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved : create_bootstrap_resource - success");
00618        internal_event(STATE_BOOTSTRAP_RESOURCE_CREATED);
00619     } else{
00620         // If resource creation fails then inform error to application
00621         tr_error("M2MInterfaceImpl::state_bootstrap_address_resolved : M2MInterface::InvalidParameters");
00622         internal_event(STATE_IDLE);
00623         _observer.error(M2MInterface::InvalidParameters);
00624     }
00625 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00626 }
00627 
00628 void M2MInterfaceImpl::state_bootstrap_resource_created( EventData */*data*/)
00629 {
00630 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00631     tr_debug("M2MInterfaceImpl::state_bootstrap_resource_created");
00632 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00633 }
00634 
00635 void M2MInterfaceImpl::state_bootstrapped( EventData */*data*/)
00636 {
00637 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00638     tr_debug("M2MInterfaceImpl::state_bootstrapped");
00639 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00640 }
00641 
00642 void M2MInterfaceImpl::state_register( EventData *data)
00643 {
00644     tr_debug("M2MInterfaceImpl::state_register");
00645     if (!_security) {
00646         M2MInterface::Error error = M2MInterface::InvalidParameters;
00647         // Start with registration preparation
00648         if(data) {
00649             M2MRegisterData *event = static_cast<M2MRegisterData *> (data);
00650             _security = event->_object;
00651             if(_security) {
00652                 if(M2MSecurity::M2MServer == _security->server_type()) {
00653                     tr_debug("M2MInterfaceImpl::state_register - server_type : M2MSecurity::M2MServer");
00654                     if(_nsdl_interface->create_nsdl_list_structure(event->_object_list)) {
00655                         tr_debug("M2MInterfaceImpl::state_register - create_nsdl_list_structure - success");
00656                         // If the nsdl resource structure is created successfully
00657                         String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri);
00658                         tr_debug("M2MInterfaceImpl::state_register - server_address %s", server_address.c_str());
00659                         String  coap;
00660                         if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
00661                              coap = COAP;
00662                         }
00663                         else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
00664                             _security->resource_value_int(M2MSecurity::SecurityMode) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
00665                         }
00666                         if(!coap.empty()) {
00667                             server_address = server_address.substr(coap.size(),
00668                                                                server_address.size() - coap.size());
00669                             process_address(server_address, _server_ip_address, _server_port);
00670 
00671                             tr_debug("M2MInterfaceImpl::state_register - IP address %s , Port %d", _server_ip_address.c_str(), _server_port);
00672                             if(!_server_ip_address.empty()) {
00673                                 // Connection related errors are coming through callback
00674                                 error = M2MInterface::ErrorNone;
00675                                 _connection_handler->resolve_server_address(_server_ip_address,_server_port,
00676                                                                             M2MConnectionObserver::LWM2MServer,
00677                                                                             _security);
00678                             }
00679                         }
00680                     }
00681                 }
00682             }
00683         }
00684         if (error != M2MInterface::ErrorNone) {
00685             tr_error("M2MInterfaceImpl::state_register - set error as M2MInterface::InvalidParameters");
00686             internal_event(STATE_IDLE);
00687             _observer.error(error);
00688         }
00689     } else {
00690         _connection_handler->resolve_server_address(_server_ip_address,_server_port,
00691                                                     M2MConnectionObserver::LWM2MServer,
00692                                                     _security);
00693     }
00694 }
00695 
00696 void M2MInterfaceImpl::process_address(const String& server_address, String& ip_address, uint16_t& port) {
00697 
00698     int colonFound = server_address.find_last_of(':'); //10
00699     if(colonFound != -1) {
00700         ip_address = server_address.substr(0,colonFound);
00701         port = atoi(server_address.substr(colonFound+1,
00702                                          server_address.size()-ip_address.size()).c_str());
00703         colonFound = ip_address.find_last_of(']');
00704         if(ip_address.compare(0,1,"[") == 0) {
00705             if(colonFound == -1) {
00706                 ip_address.clear();
00707             } else {
00708                 ip_address = ip_address.substr(1,colonFound-1);
00709             }
00710         } else if(colonFound != -1) {
00711             ip_address.clear();
00712         }
00713     }
00714 }
00715 
00716 void M2MInterfaceImpl::state_register_address_resolved( EventData *data)
00717 {
00718     tr_debug("M2MInterfaceImpl::state_register_address_resolved");
00719     if(data) {
00720         ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
00721 
00722         sn_nsdl_addr_type_e address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
00723 
00724         M2MInterface::NetworkStack stack = event->_address->_stack;
00725 
00726         if(M2MInterface::LwIP_IPv4 == stack) {
00727             tr_debug("M2MInterfaceImpl::state_register_address_resolved : IPv4 address");
00728             address_type = SN_NSDL_ADDRESS_TYPE_IPV4;
00729         } else if((M2MInterface::LwIP_IPv6 == stack) ||
00730                   (M2MInterface::Nanostack_IPv6 == stack)) {
00731             tr_debug("M2MInterfaceImpl::state_register_address_resolved : IPv6 address");
00732             address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
00733         }
00734         _connection_handler->start_listening_for_data();
00735         if(_nsdl_interface->send_register_message((uint8_t*)event->_address->_address,event->_port, address_type)) {
00736             internal_event(STATE_REGISTER_RESOURCE_CREATED);
00737         } else {
00738             // If resource creation fails then inform error to application
00739             tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::InvalidParameters");
00740             internal_event(STATE_IDLE);
00741             _observer.error(M2MInterface::InvalidParameters);
00742         }
00743     }
00744 }
00745 
00746 void M2MInterfaceImpl::state_register_resource_created( EventData */*data*/)
00747 {
00748     tr_debug("M2MInterfaceImpl::state_register_resource_created");
00749 }
00750 
00751 void M2MInterfaceImpl::state_registered( EventData */*data*/)
00752 {
00753     tr_debug("M2MInterfaceImpl::state_registered");
00754     _retry_count = 0;
00755     _register_ongoing = false;
00756     _update_register_ongoing = false;
00757     _reconnecting = false;
00758 }
00759 
00760 void M2MInterfaceImpl::state_update_registration( EventData *data)
00761 {
00762     tr_debug("M2MInterfaceImpl::state_update_registration");
00763     // Start with registration preparation
00764     if(data) {
00765         M2MUpdateRegisterData *event = static_cast<M2MUpdateRegisterData *> (data);
00766         _nsdl_interface->send_update_registration(event->_lifetime);
00767     }
00768 }
00769 
00770 void M2MInterfaceImpl::state_unregister( EventData */*data*/)
00771 {
00772     tr_debug("M2MInterfaceImpl::state_unregister");
00773     internal_event(STATE_SENDING_COAP_DATA);
00774     if(!_nsdl_interface->send_unregister_message()) {
00775         tr_error("M2MInterfaceImpl::state_unregister : M2MInterface::NotRegistered");
00776         internal_event(STATE_IDLE);
00777         _observer.error(M2MInterface::NotRegistered);
00778     }
00779 }
00780 
00781 void M2MInterfaceImpl::state_unregistered( EventData */*data*/)
00782 {
00783     tr_debug("M2MInterfaceImpl::state_unregistered");
00784     internal_event(STATE_IDLE);
00785 }
00786 
00787 void M2MInterfaceImpl::state_sending_coap_data( EventData */*data*/)
00788 {
00789     tr_debug("M2MInterfaceImpl::state_sending_coap_data");
00790     internal_event(STATE_WAITING);
00791 }
00792 
00793 void M2MInterfaceImpl::state_coap_data_sent( EventData */*data*/)
00794 {
00795     tr_debug("M2MInterfaceImpl::state_coap_data_sent");
00796     internal_event(STATE_WAITING);
00797 }
00798 
00799 void M2MInterfaceImpl::state_coap_data_received( EventData *data)
00800 {
00801     tr_debug("M2MInterfaceImpl::state_coap_data_received");
00802     if(data) {
00803         ReceivedData *event = static_cast<ReceivedData*> (data);
00804         sn_nsdl_addr_s address;
00805 
00806         M2MInterface::NetworkStack stack = event->_address->_stack;
00807 
00808         if(M2MInterface::LwIP_IPv4 == stack) {
00809             tr_debug("M2MInterfaceImpl::state_coap_data_received : IPv4 address");
00810             address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
00811             address.addr_len = 4;
00812         } else if((M2MInterface::LwIP_IPv6 == stack) ||
00813                   (M2MInterface::Nanostack_IPv6 == stack)) {
00814             tr_debug("M2MInterfaceImpl::state_coap_data_received : IPv6 address");
00815             address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
00816             address.addr_len = 16;
00817         }
00818         address.port = event->_address->_port;
00819         address.addr_ptr = (uint8_t*)event->_address->_address;
00820         address.addr_len = event->_address->_length;
00821 
00822         // Process received data
00823         internal_event(STATE_PROCESSING_COAP_DATA);
00824         if(!_nsdl_interface->process_received_data(event->_data,
00825                                                   event->_size,
00826                                                   &address)) {
00827            tr_error("M2MInterfaceImpl::state_coap_data_received : M2MInterface::ResponseParseFailed");
00828             _observer.error(M2MInterface::ResponseParseFailed);
00829         }
00830     }
00831 }
00832 
00833 void M2MInterfaceImpl::state_processing_coap_data( EventData */*data*/)
00834 {
00835     tr_debug("M2MInterfaceImpl::state_processing_coap_data");
00836     internal_event(STATE_WAITING);
00837 }
00838 
00839 void M2MInterfaceImpl::state_coap_data_processed( EventData */*data*/)
00840 {
00841     tr_debug("M2MInterfaceImpl::state_coap_data_processed");
00842     internal_event(STATE_WAITING);
00843 }
00844 
00845 void M2MInterfaceImpl::state_waiting( EventData */*data*/)
00846 {
00847     tr_debug("M2MInterfaceImpl::state_waiting");
00848 }
00849 
00850 // generates an external event. called once per external event
00851 // to start the state machine executing
00852 void M2MInterfaceImpl::external_event(uint8_t new_state,
00853                                      EventData* p_data)
00854 {
00855     tr_debug("M2MInterfaceImpl::external_event : new state %d", new_state);
00856     // if we are supposed to ignore this event
00857     if (new_state == EVENT_IGNORED) {
00858         tr_debug("M2MInterfaceImpl::external_event : new state is EVENT_IGNORED");
00859         // just delete the event data, if any
00860         if (p_data) {
00861             delete p_data;
00862             p_data = NULL;
00863         }
00864         _event_ignored = true;
00865     }
00866     else {
00867         tr_debug("M2MInterfaceImpl::external_event : handle new state");
00868         // generate the event and execute the state engine
00869         internal_event(new_state, p_data);
00870     }
00871 }
00872 
00873 // generates an internal event. called from within a state
00874 // function to transition to a new state
00875 void M2MInterfaceImpl::internal_event(uint8_t new_state,
00876                                       EventData* p_data)
00877 {
00878     tr_debug("M2MInterfaceImpl::internal_event : new state %d", new_state);
00879     _event_data = p_data;
00880     _event_generated = true;
00881     _current_state = new_state;
00882     state_engine();
00883 }
00884 
00885 // the state engine executes the state machine states
00886 void M2MInterfaceImpl::state_engine (void)
00887 {
00888     tr_debug("M2MInterfaceImpl::state_engine");
00889     EventData* p_data_temp = NULL;
00890 
00891     // while events are being generated keep executing states
00892     while (_event_generated) {
00893         p_data_temp = _event_data;  // copy of event data pointer
00894         _event_data = NULL;       // event data used up, reset ptr
00895         _event_generated = false;  // event used up, reset flag
00896 
00897         assert(_current_state < _max_states);
00898 
00899         state_function( _current_state, p_data_temp );
00900 
00901         // if event data was used, then delete it
00902         if (p_data_temp) {
00903             delete p_data_temp;
00904             p_data_temp = NULL;
00905         }
00906     }
00907 }
00908 
00909 void M2MInterfaceImpl::state_function( uint8_t current_state, EventData* data )
00910 {
00911     switch( current_state ) {
00912         case STATE_IDLE:
00913             M2MInterfaceImpl::state_idle(data);
00914             break;
00915         case STATE_BOOTSTRAP:
00916         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00917             M2MInterfaceImpl::state_bootstrap(data);
00918         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00919             break;
00920         case STATE_BOOTSTRAP_ADDRESS_RESOLVED:
00921         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00922             M2MInterfaceImpl::state_bootstrap_address_resolved(data);
00923         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00924             break;
00925         case STATE_BOOTSTRAP_RESOURCE_CREATED:
00926         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00927             M2MInterfaceImpl::state_bootstrap_resource_created(data);
00928         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00929             break;
00930         case STATE_BOOTSTRAPPED:
00931         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00932             M2MInterfaceImpl::state_bootstrapped(data);
00933         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00934             break;
00935         case STATE_REGISTER:
00936             M2MInterfaceImpl::state_register(data);
00937             break;
00938         case STATE_REGISTER_ADDRESS_RESOLVED:
00939             M2MInterfaceImpl::state_register_address_resolved(data);
00940             break;
00941         case STATE_REGISTER_RESOURCE_CREATED:
00942             M2MInterfaceImpl::state_register_resource_created(data);
00943             break;
00944         case STATE_REGISTERED:
00945             M2MInterfaceImpl::state_registered(data);
00946             break;
00947         case STATE_UPDATE_REGISTRATION:
00948             M2MInterfaceImpl::state_update_registration(data);
00949             break;
00950         case STATE_UNREGISTER:
00951             M2MInterfaceImpl::state_unregister(data);
00952             break;
00953         case STATE_UNREGISTERED:
00954             M2MInterfaceImpl::state_unregistered(data);
00955             break;
00956         case STATE_SENDING_COAP_DATA:
00957             M2MInterfaceImpl::state_sending_coap_data(data);
00958             break;
00959         case STATE_COAP_DATA_SENT:
00960             M2MInterfaceImpl::state_coap_data_sent(data);
00961             break;
00962         case STATE_COAP_DATA_RECEIVED:
00963             M2MInterfaceImpl::state_coap_data_received(data);
00964             break;
00965         case STATE_PROCESSING_COAP_DATA:
00966             M2MInterfaceImpl::state_processing_coap_data(data);
00967             break;
00968         case STATE_COAP_DATA_PROCESSED:
00969             M2MInterfaceImpl::state_coap_data_processed(data);
00970             break;
00971         case STATE_WAITING:
00972             M2MInterfaceImpl::state_waiting(data);
00973             break;
00974     }
00975 }