Mbed Cloud example program for workshop in W27 2018.

Dependencies:   MMA7660 LM75B

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 
00017 // Needed for PRIu64 on FreeRTOS
00018 #include <stdio.h>
00019 // Note: this macro is needed on armcc to get the the PRI*32 macros
00020 // from inttypes.h in a C++ code.
00021 #ifndef __STDC_FORMAT_MACROS
00022 #define __STDC_FORMAT_MACROS
00023 #endif
00024 #include <inttypes.h>
00025 
00026 #include <assert.h>
00027 #include <stdlib.h>
00028 #include <stdio.h>
00029 #include <time.h>
00030 #include "include/m2minterfaceimpl.h"
00031 #include "include/eventdata.h"
00032 #include "mbed-client/m2minterfaceobserver.h"
00033 #include "mbed-client/m2mconnectionhandler.h"
00034 #include "mbed-client/m2mconnectionsecurity.h"
00035 #include "include/m2mnsdlinterface.h"
00036 #include "mbed-client/m2msecurity.h"
00037 #include "mbed-client/m2mtimer.h"
00038 #include "mbed-trace/mbed_trace.h"
00039 #include "randLIB.h"
00040 
00041 #include <stdlib.h>
00042 
00043 #define TRACE_GROUP "mClt"
00044 
00045 #define RESOLVE_SEC_MODE(mode)  ((mode == M2MInterface::TCP || mode == M2MInterface::TCP_QUEUE) ? M2MConnectionSecurity::TLS : M2MConnectionSecurity::DTLS)
00046 
00047 M2MInterfaceImpl::M2MInterfaceImpl(M2MInterfaceObserver& observer,
00048                                    const String &ep_name,
00049                                    const String &ep_type,
00050                                    const int32_t l_time,
00051                                    const uint16_t listen_port,
00052                                    const String &dmn,
00053                                    M2MInterface::BindingMode mode,
00054                                    M2MInterface::NetworkStack stack,
00055                                    const String &con_addr)
00056 : _event_data(NULL),
00057   _registration_flow_timer(NULL),
00058   _server_port(0),
00059   _listen_port(listen_port),
00060   _life_time(l_time),
00061   _register_server(NULL),
00062   _queue_sleep_timer(*this),
00063   _retry_timer(*this),
00064   _callback_handler(NULL),
00065   _max_states( STATE_MAX_STATES ),
00066   _event_ignored(false),
00067   _event_generated(false),
00068   _reconnecting(false),
00069   _retry_timer_expired(false),
00070   _bootstrapped(true), // True as default to get it working with connector only configuration
00071   _queue_mode_timer_ongoing(false),
00072   _current_state(0),
00073   _binding_mode(mode),
00074   _reconnection_state(M2MInterfaceImpl::None),
00075   _observer(observer),
00076   _security_connection( new M2MConnectionSecurity( RESOLVE_SEC_MODE(mode) )),
00077   _connection_handler(*this, _security_connection, mode, stack),
00078   _nsdl_interface(*this, _connection_handler),
00079   _security(NULL)
00080 {
00081     tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -IN");
00082     //TODO:Increase the range from 1 to 100 seconds
00083     randLIB_seed_random();
00084     // Range is from 2 to 10
00085     _initial_reconnection_time = randLIB_get_random_in_range(2, 10);
00086 
00087     tr_info("M2MInterfaceImpl::M2MInterfaceImpl() initial random time %d\n", _initial_reconnection_time);
00088     _reconnection_time = _initial_reconnection_time;
00089 
00090 #ifndef DISABLE_ERROR_DESCRIPTION
00091     memset(_error_description, 0, sizeof(_error_description));
00092 #endif
00093 
00094     _nsdl_interface.create_endpoint(ep_name,
00095                                      ep_type,
00096                                      _life_time,
00097                                      dmn,
00098                                      (uint8_t)_binding_mode,
00099                                      con_addr);
00100 
00101     //Here we must use TCP still
00102     _connection_handler.bind_connection(_listen_port);
00103 
00104     // We need this timer only in case of TCP
00105     if (_binding_mode == M2MInterface::TCP ||
00106         _binding_mode == M2MInterface::TCP_QUEUE ) {
00107         _registration_flow_timer = new M2MTimer(*this);
00108     }
00109     tr_debug("M2MInterfaceImpl::M2MInterfaceImpl() -OUT");
00110 }
00111 
00112 
00113 M2MInterfaceImpl::~M2MInterfaceImpl()
00114 {
00115     tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - IN");
00116     delete _registration_flow_timer;
00117     _security_connection = NULL;
00118     tr_debug("M2MInterfaceImpl::~M2MInterfaceImpl() - OUT");
00119 }
00120 
00121 void M2MInterfaceImpl::bootstrap(M2MSecurity *security)
00122 {
00123 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00124     tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - IN");
00125     _retry_timer.stop_timer();
00126     _security = NULL;
00127     if(!security) {
00128         set_error_description(ERROR_REASON_1);
00129         _observer.error(M2MInterface::InvalidParameters);
00130         return;
00131     }
00132     // Transition to a new state based upon
00133     // the current state of the state machine
00134     M2MSecurityData data;
00135     data._object = security;
00136     BEGIN_TRANSITION_MAP                                    // - Current State -
00137         TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP)              // state_idle
00138         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00139         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00140         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00141         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
00142         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
00143         TRANSITION_MAP_ENTRY (STATE_BOOTSTRAP)              // state_bootstrapped
00144         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00145         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00146         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_registered
00147         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
00148         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00149         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00150         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
00151         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
00152         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
00153         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
00154         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
00155         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_waiting
00156     END_TRANSITION_MAP(&data)
00157     if(_event_ignored) {
00158         _event_ignored = false;
00159         set_error_description(ERROR_REASON_2);
00160         _observer.error(M2MInterface::NotAllowed);
00161     }
00162     tr_debug("M2MInterfaceImpl::bootstrap(M2MSecurity *security) - OUT");
00163 #else
00164     set_error_description(ERROR_REASON_3);
00165     _observer.error(M2MInterface::NotAllowed);
00166 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00167 }
00168 
00169 void M2MInterfaceImpl::cancel_bootstrap()
00170 {
00171 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00172 //TODO: Do we need this ?
00173 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00174 }
00175 
00176 void M2MInterfaceImpl::register_object(M2MSecurity *security, const M2MObjectList &object_list)
00177 {
00178     tr_debug("M2MInterfaceImpl::register_object - IN");
00179     if(!security) {
00180         set_error_description(ERROR_REASON_4);
00181         _observer.error(M2MInterface::InvalidParameters);
00182         return;
00183     }
00184     // Transition to a new state based upon
00185     // the current state of the state machine
00186     //TODO: manage register object in a list.
00187     _connection_handler.claim_mutex();
00188     _register_server = security;
00189     M2MRegisterData data;
00190     data._object = security;
00191     data._object_list = object_list;
00192     BEGIN_TRANSITION_MAP                                    // - Current State -
00193         TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_idle
00194         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00195         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00196         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00197         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
00198         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
00199         TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_bootstrapped
00200         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00201         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00202         TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_registered
00203         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
00204         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00205         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00206         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
00207         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
00208         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
00209         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
00210         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
00211         TRANSITION_MAP_ENTRY (STATE_REGISTER)               // state_waiting
00212     END_TRANSITION_MAP(&data)
00213     if(_event_ignored) {
00214         _event_ignored = false;
00215         set_error_description(ERROR_REASON_5);
00216         _observer.error(M2MInterface::NotAllowed);
00217     }
00218     _connection_handler.release_mutex();
00219     tr_debug("M2MInterfaceImpl::register_object - OUT");
00220 }
00221 
00222 void M2MInterfaceImpl::update_registration(M2MSecurity *security_object, const uint32_t lifetime)
00223 {
00224     tr_debug("M2MInterfaceImpl::update_registration()");
00225     _connection_handler.claim_mutex();
00226     M2MUpdateRegisterData data;
00227     data._object = security_object;
00228     data._lifetime = lifetime;
00229     start_register_update(&data);
00230     _connection_handler.release_mutex();
00231 }
00232 
00233 void M2MInterfaceImpl::update_registration(M2MSecurity *security_object,
00234                                            const M2MObjectList &object_list,
00235                                            const uint32_t lifetime)
00236 {
00237     tr_debug("M2MInterfaceImpl::update_registration - with object list");
00238     _connection_handler.claim_mutex();
00239     M2MUpdateRegisterData data;
00240     data._object = security_object;
00241     data._lifetime = lifetime;
00242     data._object_list = object_list;
00243     start_register_update(&data);
00244     _connection_handler.release_mutex();
00245 }
00246 
00247 void M2MInterfaceImpl::unregister_object(M2MSecurity* /*security*/)
00248 {
00249     tr_debug("M2MInterfaceImpl::unregister_object - current state %d", _current_state);
00250     _connection_handler.claim_mutex();
00251     // Transition to a new state based upon
00252     // the current state of the state machine
00253     BEGIN_TRANSITION_MAP                                // - Current State -
00254         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_idle
00255         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
00256         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
00257         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
00258         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
00259         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
00260         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
00261         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
00262         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
00263         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_registered
00264         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_update_registration
00265         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
00266         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
00267         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_sending_coap_data
00268         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_coap_data_sent
00269         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_coap_data_received
00270         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_processing_coap_data
00271         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_coap_data_processed
00272         TRANSITION_MAP_ENTRY (STATE_UNREGISTER)             // state_waiting
00273     END_TRANSITION_MAP(NULL)
00274     if(_event_ignored) {
00275         _event_ignored = false;
00276         set_error_description(ERROR_REASON_6);
00277         _observer.error(M2MInterface::NotAllowed);
00278     }
00279     _connection_handler.release_mutex();
00280     tr_debug("M2MInterfaceImpl::unregister_object - OUT");
00281 }
00282 
00283 void M2MInterfaceImpl::set_queue_sleep_handler(callback_handler handler)
00284 {
00285     _callback_handler = handler;
00286 }
00287 
00288 void M2MInterfaceImpl::set_random_number_callback(random_number_cb callback)
00289 {
00290     if(_security_connection) {
00291         _security_connection->set_random_number_callback(callback);
00292     }
00293 }
00294 
00295 void M2MInterfaceImpl::set_entropy_callback(entropy_cb callback)
00296 {
00297     if(_security_connection) {
00298         _security_connection->set_entropy_callback(callback);
00299     }
00300 }
00301 
00302 void M2MInterfaceImpl::set_platform_network_handler(void *handler)
00303 {
00304     _connection_handler.set_platform_network_handler(handler);
00305 }
00306 
00307 void M2MInterfaceImpl::coap_message_ready(uint8_t *data_ptr,
00308                                           uint16_t data_len,
00309                                           sn_nsdl_addr_s *address_ptr)
00310 {
00311     tr_debug("M2MInterfaceImpl::coap_message_ready");
00312     if (_current_state != STATE_IDLE) {
00313         internal_event(STATE_SENDING_COAP_DATA);
00314         if(!_connection_handler.send_data(data_ptr,data_len,address_ptr)) {
00315             internal_event( STATE_IDLE);
00316             tr_error("M2MInterfaceImpl::coap_message_ready() - M2MInterface::NetworkError");
00317             if (!_reconnecting) {
00318                 _queue_mode_timer_ongoing = false;
00319                 socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR, true);
00320             } else {
00321                 socket_error(M2MConnectionHandler::SOCKET_ABORT);
00322             }
00323         }
00324     }
00325 }
00326 
00327 void M2MInterfaceImpl::client_registered(M2MServer *server_object)
00328 {
00329     tr_info("M2MInterfaceImpl::client_registered");
00330     internal_event(STATE_REGISTERED);
00331     //Inform client is registered.
00332     //TODO: manage register object in a list.
00333     _observer.object_registered(_register_server,*server_object);
00334 }
00335 
00336 void M2MInterfaceImpl::registration_updated(const M2MServer &server_object)
00337 {
00338     tr_info("M2MInterfaceImpl::registration_updated");
00339     internal_event(STATE_REGISTERED);
00340     _observer.registration_updated(_register_server,server_object);
00341 }
00342 
00343 void M2MInterfaceImpl::registration_error(uint8_t error_code, bool retry)
00344 {
00345     tr_error("M2MInterfaceImpl::registration_error code [%d]", error_code);
00346     // Try to register again
00347     if (retry) {
00348         _queue_mode_timer_ongoing = false;
00349         if (error_code == M2MInterface::UnregistrationFailed) {
00350             _reconnection_state = M2MInterfaceImpl::Unregistration;
00351         }
00352         socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR);
00353     } else {
00354         _security = NULL;
00355         internal_event(STATE_IDLE);
00356         if (error_code == M2MInterface::UnregistrationFailed) {
00357             set_error_description(ERROR_REASON_24);
00358         } else {
00359             set_error_description(ERROR_REASON_8);
00360         }
00361         _observer.error((M2MInterface::Error)error_code);
00362     }
00363 }
00364 
00365 void M2MInterfaceImpl::client_unregistered()
00366 {
00367     tr_info("M2MInterfaceImpl::client_unregistered()");
00368     internal_event(STATE_UNREGISTERED);
00369     //TODO: manage register object in a list.
00370     _observer.object_unregistered(_register_server);
00371 }
00372 
00373 void M2MInterfaceImpl::bootstrap_done()
00374 {
00375 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00376     tr_info("M2MInterfaceImpl::bootstrap_done");
00377     _reconnection_time = _initial_reconnection_time;
00378     _reconnecting = false;
00379     _reconnection_state = M2MInterfaceImpl::None;
00380     _bootstrapped = true;
00381     if (_registration_flow_timer) {
00382         _registration_flow_timer->stop_timer();
00383     }
00384     internal_event(STATE_BOOTSTRAPPED);
00385     _observer.bootstrap_done(_nsdl_interface.get_security_object());
00386 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00387 }
00388 
00389 void M2MInterfaceImpl::bootstrap_wait()
00390 {
00391 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00392     tr_info("M2MInterfaceImpl::bootstrap_wait");
00393     internal_event(STATE_BOOTSTRAP_WAIT);
00394 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00395 }
00396 
00397 void M2MInterfaceImpl::bootstrap_error_wait(const char *reason)
00398 {
00399 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00400     tr_error("M2MInterfaceImpl::bootstrap_error_wait");
00401     set_error_description(reason);
00402     internal_event(STATE_BOOTSTRAP_ERROR_WAIT);
00403 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00404 }
00405 
00406 void M2MInterfaceImpl::bootstrap_error(const char *reason)
00407 {
00408 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00409     tr_error("M2MInterfaceImpl::bootstrap_error(%s)", reason);
00410     _bootstrapped = false;
00411     if (_registration_flow_timer) {
00412         _registration_flow_timer->stop_timer();
00413     }
00414 
00415     _reconnection_state = M2MInterfaceImpl::None;
00416 
00417     set_error_description(reason);
00418 
00419     _observer.error(M2MInterface::BootstrapFailed);
00420 
00421     internal_event(STATE_IDLE);
00422     _reconnecting = true;
00423     _connection_handler.stop_listening();
00424 
00425     _retry_timer_expired = false;
00426     _retry_timer.start_timer(_reconnection_time * 1000,
00427                               M2MTimerObserver::RetryTimer);
00428     tr_info("M2MInterfaceImpl::bootstrap_error - reconnecting in %" PRIu64 "(s)", _reconnection_time);
00429     _reconnection_time = _reconnection_time * RECONNECT_INCREMENT_FACTOR;
00430     if(_reconnection_time >= MAX_RECONNECT_TIMEOUT) {
00431         _reconnection_time = MAX_RECONNECT_TIMEOUT;
00432     }
00433 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00434 }
00435 
00436 void M2MInterfaceImpl::coap_data_processed()
00437 {
00438     tr_debug("M2MInterfaceImpl::coap_data_processed()");
00439     internal_event(STATE_COAP_DATA_PROCESSED);
00440 }
00441 
00442 void M2MInterfaceImpl::value_updated(M2MBase *base)
00443 {
00444     tr_debug("M2MInterfaceImpl::value_updated");
00445     if(base) {
00446         M2MBase::BaseType type = base->base_type();
00447         _observer.value_updated(base, type);
00448     }
00449 }
00450 
00451 void M2MInterfaceImpl::data_available(uint8_t* data,
00452                                       uint16_t data_size,
00453                                       const M2MConnectionObserver::SocketAddress &address)
00454 {
00455     tr_debug("M2MInterfaceImpl::data_available");
00456     ReceivedData event;
00457     event._data = data;
00458     event._size = data_size;
00459     event._address = &address;
00460     internal_event(STATE_COAP_DATA_RECEIVED, &event);
00461 }
00462 
00463 void M2MInterfaceImpl::socket_error(uint8_t error_code, bool retry)
00464 {
00465     // Bootstrap completed once PEER CLOSE notify received from the server.
00466     if (_current_state == STATE_BOOTSTRAP_WAIT &&
00467         error_code == M2MConnectionHandler::SSL_PEER_CLOSED) {
00468         _security = NULL;
00469         bootstrap_done();
00470         return;
00471     }
00472 
00473     tr_error("M2MInterfaceImpl::socket_error: (%d), retry (%d), reconnecting (%d), reconnection_state (%d)",
00474              error_code, retry, _reconnecting, (int)_reconnection_state);
00475 
00476     // Ignore errors while client is sleeping
00477     if(queue_mode()) {
00478         if(_callback_handler && _queue_mode_timer_ongoing) {
00479             tr_info("M2MInterfaceImpl::socket_error - Queue Mode - don't try to reconnect while in QueueMode");
00480             return;
00481         }
00482     }
00483     _queue_sleep_timer.stop_timer();
00484 
00485     if (_registration_flow_timer) {
00486         _registration_flow_timer->stop_timer();
00487     }
00488 
00489     _queue_sleep_timer.stop_timer();
00490 
00491     // Don't change flag state if unregistration has failed.
00492     // This info is needed for continuing unregistration process after client is registered again.
00493     if (_reconnection_state != M2MInterfaceImpl::Unregistration && _reconnection_state != M2MInterfaceImpl::FullRegistration) {
00494         _reconnection_state = M2MInterfaceImpl::WithUpdate;
00495     }
00496 
00497     const char *error_code_des;
00498     M2MInterface::Error error = M2MInterface::ErrorNone;
00499     switch (error_code) {
00500     case M2MConnectionHandler::SSL_CONNECTION_ERROR:
00501         error = M2MInterface::SecureConnectionFailed;
00502         error_code_des = ERROR_SECURE_CONNECTION;
00503         break;
00504     case M2MConnectionHandler::DNS_RESOLVING_ERROR:
00505         error = M2MInterface::DnsResolvingFailed;
00506         error_code_des = ERROR_DNS;
00507         break;
00508     case M2MConnectionHandler::SOCKET_READ_ERROR:
00509         error = M2MInterface::NetworkError;
00510         error_code_des = ERROR_NETWORK;
00511         break;
00512     case M2MConnectionHandler::SOCKET_SEND_ERROR:
00513         error = M2MInterface::NetworkError;
00514         error_code_des = ERROR_NETWORK;
00515         break;
00516     case M2MConnectionHandler::SSL_HANDSHAKE_ERROR:
00517         error = M2MInterface::SecureConnectionFailed;
00518         error_code_des = ERROR_SECURE_CONNECTION;
00519         break;
00520     case M2MConnectionHandler::SOCKET_ABORT:
00521         error = M2MInterface::NetworkError;
00522         error_code_des = ERROR_NETWORK;
00523         break;
00524     default:
00525         error_code_des = ERROR_NO;
00526         break;
00527     }
00528 
00529     internal_event(STATE_IDLE);
00530     // Try to do reconnecting
00531     if (retry) {
00532         _reconnecting = true;
00533         _connection_handler.stop_listening();
00534         _retry_timer_expired = false;
00535         _retry_timer.start_timer(_reconnection_time * 1000,
00536                                   M2MTimerObserver::RetryTimer);
00537         tr_info("M2MInterfaceImpl::socket_error - reconnecting in %" PRIu64 "(s)", _reconnection_time);
00538         _reconnection_time = _reconnection_time * RECONNECT_INCREMENT_FACTOR;
00539         if(_reconnection_time >= MAX_RECONNECT_TIMEOUT) {
00540             _reconnection_time = MAX_RECONNECT_TIMEOUT;
00541         }
00542 #ifndef DISABLE_ERROR_DESCRIPTION
00543         snprintf(_error_description, sizeof(_error_description), ERROR_REASON_9, error_code_des);
00544 #endif
00545     }
00546     // Inform application
00547     if (!retry && M2MInterface::ErrorNone != error) {
00548         tr_info("M2MInterfaceImpl::socket_error - send error to application");
00549         _connection_handler.stop_listening();
00550         _retry_timer.stop_timer();
00551         _security = NULL;
00552         _reconnecting = false;
00553         _reconnection_time = _initial_reconnection_time;
00554         _reconnection_state = M2MInterfaceImpl::None;
00555 #ifndef DISABLE_ERROR_DESCRIPTION
00556         snprintf(_error_description, sizeof(_error_description), ERROR_REASON_10, error_code_des);
00557 #endif
00558     }
00559     if(M2MInterface::ErrorNone != error) {
00560         _observer.error(error);
00561     }
00562 }
00563 
00564 void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &address,
00565                                      M2MConnectionObserver::ServerType server_type,
00566                                      const uint16_t server_port)
00567 {
00568     tr_debug("M2MInterfaceImpl::address_ready");
00569     ResolvedAddressData data;
00570     data._address = &address;
00571     data._port = server_port;
00572     if( M2MConnectionObserver::Bootstrap == server_type) {
00573         tr_info("M2MInterfaceImpl::address_ready() Server Type Bootstrap");
00574         internal_event(STATE_BOOTSTRAP_ADDRESS_RESOLVED, &data);
00575     } else {
00576         tr_info("M2MInterfaceImpl::address_ready() Server Type LWM2M");
00577         internal_event(STATE_REGISTER_ADDRESS_RESOLVED, &data);
00578     }
00579 }
00580 
00581 void M2MInterfaceImpl::data_sent()
00582 {
00583     tr_debug("M2MInterfaceImpl::data_sent()");
00584     if(queue_mode()) {
00585         if(_callback_handler && (_nsdl_interface.get_unregister_ongoing() == false)) {
00586             _queue_sleep_timer.stop_timer();
00587             // Multiply by two to get enough time for coap retransmissions.
00588             _queue_sleep_timer.start_timer(MBED_CLIENT_RECONNECTION_COUNT*MBED_CLIENT_RECONNECTION_INTERVAL*1000*2,
00589                                             M2MTimerObserver::QueueSleep);
00590         }
00591     }
00592 
00593     if (_current_state == STATE_BOOTSTRAP_ERROR_WAIT) {
00594         // bootstrap_error to be called only after we have sent the last ACK.
00595         // Otherwise client will goto reconnection mode before ACK has sent.
00596         bootstrap_error(_error_description);
00597     } else if (_current_state != STATE_BOOTSTRAP_WAIT) {
00598         internal_event(STATE_COAP_DATA_SENT);
00599     }
00600 }
00601 
00602 void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type)
00603 {
00604     if(M2MTimerObserver::QueueSleep == type) {
00605         tr_debug("M2MInterfaceImpl::timer_expired() - sleep");
00606         M2MTimer &timer = _nsdl_interface.get_nsdl_execution_timer();
00607         timer.stop_timer();
00608         _queue_mode_timer_ongoing = true;
00609         if(_callback_handler) {
00610             _callback_handler();
00611         }
00612     }
00613     else if (M2MTimerObserver::RetryTimer == type) {
00614         tr_debug("M2MInterfaceImpl::timer_expired() - retry");
00615         _retry_timer_expired = true;
00616         if (_bootstrapped) {
00617             internal_event(STATE_REGISTER);
00618         } else {
00619             internal_event(STATE_BOOTSTRAP);
00620         }
00621     }
00622     else if (M2MTimerObserver::BootstrapFlowTimer == type) {
00623 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00624         tr_debug("M2MInterfaceImpl::timer_expired() - bootstrap");
00625         _bootstrapped = false;
00626         if (_registration_flow_timer) {
00627             _registration_flow_timer->stop_timer();
00628         }
00629         bootstrap_error(ERROR_REASON_23);
00630 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00631     }
00632     else if (M2MTimerObserver::RegistrationFlowTimer == type) {
00633         tr_debug("M2MInterfaceImpl::timer_expired() - register");
00634         registration_error(M2MInterface::Timeout, true);
00635     }
00636 }
00637 
00638 // state machine sits here.
00639 void M2MInterfaceImpl::state_idle(EventData* /*data*/)
00640 {
00641     tr_debug("M2MInterfaceImpl::state_idle");
00642     _nsdl_interface.stop_timers();
00643     _queue_sleep_timer.stop_timer();
00644 }
00645 
00646 void M2MInterfaceImpl::state_bootstrap(EventData *data)
00647 {
00648 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00649     tr_debug("M2MInterfaceImpl::state_bootstrap");
00650     // Start with bootstrapping preparation
00651     _bootstrapped = false;
00652     M2MSecurityData *event = static_cast<M2MSecurityData *> (data);
00653     if(!_security) {
00654         M2MInterface::Error error = M2MInterface::InvalidParameters;
00655         if (event) {
00656             _security = event->_object;
00657             if(_security) {
00658                 int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
00659                 tr_info("M2MInterfaceImpl::state_bootstrap - bs_id = %d", bs_id);
00660                 if(bs_id >= 0) {
00661                     String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri, bs_id);
00662                     _nsdl_interface.set_server_address(server_address.c_str());
00663                     tr_info("M2MInterfaceImpl::state_bootstrap - server_address %s", server_address.c_str());
00664                     String coap;
00665                     if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
00666                          coap = COAP;
00667                     }
00668                     else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
00669                         _security->resource_value_int(M2MSecurity::SecurityMode, bs_id) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
00670                     }
00671                     if(!coap.empty()) {
00672                         server_address = server_address.substr(coap.size(),
00673                                                            server_address.size()-coap.size());
00674 
00675                         process_address(server_address, _server_ip_address, _server_port);
00676 
00677                         tr_info("M2MInterfaceImpl::state_bootstrap - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00678                         // If bind and resolving server address succeed then proceed else
00679                         // return error to the application and go to Idle state.
00680                         if(!_server_ip_address.empty()) {
00681                             error = M2MInterface::ErrorNone;
00682                             if (_registration_flow_timer) {
00683                                 _registration_flow_timer->stop_timer();
00684                                 _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00685                                                               M2MTimerObserver::BootstrapFlowTimer);
00686                             }
00687                             _connection_handler.resolve_server_address(_server_ip_address,
00688                                                                         _server_port,
00689                                                                         M2MConnectionObserver::Bootstrap,
00690                                                                         _security);
00691                         }
00692                     }
00693                 }
00694             }
00695         }
00696         if (error != M2MInterface::ErrorNone) {
00697             tr_error("M2MInterfaceImpl::state_bootstrap - set error as M2MInterface::InvalidParameters");
00698             internal_event(STATE_IDLE);
00699             set_error_description(ERROR_REASON_11);
00700             _observer.error(error);
00701         }
00702     } else {
00703         _listen_port = 0;
00704         _connection_handler.bind_connection(_listen_port);
00705         if (_registration_flow_timer) {
00706             _registration_flow_timer->stop_timer();
00707             _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00708                                           M2MTimerObserver::BootstrapFlowTimer);
00709         }
00710         tr_info("M2MInterfaceImpl::state_bootstrap (reconnect) - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00711         _connection_handler.resolve_server_address(_server_ip_address,
00712                                                     _server_port,
00713                                                     M2MConnectionObserver::Bootstrap,
00714                                                     _security);
00715     }
00716 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00717 }
00718 
00719 void M2MInterfaceImpl::state_bootstrap_address_resolved( EventData *data)
00720 {
00721 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00722     tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved");
00723     if (data) {
00724         ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
00725         sn_nsdl_addr_s address;
00726 
00727         M2MInterface::NetworkStack stack = event->_address->_stack;
00728 
00729         if(M2MInterface::LwIP_IPv4 == stack) {
00730             tr_info("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv4 address");
00731             address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
00732         } else if((M2MInterface::LwIP_IPv6 == stack) ||
00733                   (M2MInterface::Nanostack_IPv6 == stack)) {
00734             tr_info("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv6 address");
00735             address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
00736         }
00737         address.port = event->_port;
00738         address.addr_ptr = (uint8_t*)event->_address->_address;
00739         address.addr_len = event->_address->_length;
00740         _connection_handler.start_listening_for_data();
00741 
00742         if(_nsdl_interface.create_bootstrap_resource(&address)) {
00743            internal_event(STATE_BOOTSTRAP_RESOURCE_CREATED);
00744         } else{
00745             // If resource creation fails then inform error to application
00746             tr_error("M2MInterfaceImpl::state_bootstrap_address_resolved : M2MInterface::InvalidParameters");
00747             internal_event(STATE_IDLE);
00748             set_error_description(ERROR_REASON_12);
00749             _observer.error(M2MInterface::InvalidParameters);
00750         }
00751     }
00752 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00753 }
00754 
00755 void M2MInterfaceImpl::state_bootstrap_resource_created( EventData */*data*/)
00756 {
00757 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00758     tr_debug("M2MInterfaceImpl::state_bootstrap_resource_created");
00759 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00760 }
00761 
00762 void M2MInterfaceImpl::state_bootstrapped( EventData */*data*/)
00763 {
00764 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00765     tr_debug("M2MInterfaceImpl::state_bootstrapped");
00766 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00767 }
00768 
00769 void M2MInterfaceImpl::state_register(EventData *data)
00770 {
00771     tr_debug("M2MInterfaceImpl::state_register");
00772     M2MRegisterData *event = static_cast<M2MRegisterData *> (data);
00773     if (!_security) {
00774         M2MInterface::Error error = M2MInterface::InvalidParameters;
00775         // Start with registration preparation
00776         if(event) {
00777             _security = event->_object;
00778             if(_security) {
00779                 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
00780                 if(m2m_id >= 0) {
00781                     if(_nsdl_interface.create_nsdl_list_structure(event->_object_list)) {
00782                         // If the nsdl resource structure is created successfully
00783                         String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
00784                         _nsdl_interface.set_server_address(server_address.c_str());
00785                         tr_info("M2MInterfaceImpl::state_register - server_address %s", server_address.c_str());
00786                         String  coap;
00787                         if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
00788                              coap = COAP;
00789                         }
00790                         else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
00791                             _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
00792                         }
00793                         if(!coap.empty()) {
00794                             server_address = server_address.substr(coap.size(),
00795                                                                server_address.size() - coap.size());
00796                             process_address(server_address, _server_ip_address, _server_port);
00797 
00798                             tr_info("M2MInterfaceImpl::state_register - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00799                             if(!_server_ip_address.empty()) {
00800                                 // Connection related errors are coming through callback
00801                                 if (_registration_flow_timer) {
00802                                     _registration_flow_timer->stop_timer();
00803                                     _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00804                                                                   M2MTimerObserver::RegistrationFlowTimer);
00805                                 }
00806                                 _reconnection_state = M2MInterfaceImpl::FullRegistration;
00807                                 error = M2MInterface::ErrorNone;
00808                                 _connection_handler.resolve_server_address(_server_ip_address,_server_port,
00809                                                                             M2MConnectionObserver::LWM2MServer,
00810                                                                             _security);
00811                             }
00812                         }
00813                     } else {
00814                         tr_error("M2MInterfaceImpl::state_register - fail to create nsdl list structure!");
00815                     }
00816                 }
00817             }
00818         }
00819         if (error != M2MInterface::ErrorNone) {
00820             tr_error("M2MInterfaceImpl::state_register - set error as M2MInterface::InvalidParameters");
00821             internal_event(STATE_IDLE);
00822             set_error_description(ERROR_REASON_13);
00823             _observer.error(error);
00824         }
00825     } else {
00826         _listen_port = 0;
00827         if (event) {
00828             _nsdl_interface.create_nsdl_list_structure(event->_object_list);
00829         }
00830         _connection_handler.bind_connection(_listen_port);
00831         if (_registration_flow_timer) {
00832             _registration_flow_timer->stop_timer();
00833             _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00834                                           M2MTimerObserver::RegistrationFlowTimer);
00835         }
00836         _reconnection_state = M2MInterfaceImpl::FullRegistration;
00837         tr_info("M2MInterfaceImpl::state_register (reconnect) - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00838         _connection_handler.resolve_server_address(_server_ip_address,_server_port,
00839                                                     M2MConnectionObserver::LWM2MServer,
00840                                                     _security);
00841     }
00842 }
00843 
00844 void M2MInterfaceImpl::process_address(const String& server_address, String& ip_address, uint16_t& port) {
00845 
00846     int colonFound = server_address.find_last_of(':'); //10
00847     if(colonFound != -1) {
00848         ip_address = server_address.substr(0,colonFound);
00849         port = atoi(server_address.substr(colonFound+1,
00850                                          server_address.size()-ip_address.size()).c_str());
00851         colonFound = ip_address.find_last_of(']');
00852         if(ip_address.compare(0,1,"[") == 0) {
00853             if(colonFound == -1) {
00854                 ip_address.clear();
00855             } else {
00856                 ip_address = ip_address.substr(1,colonFound-1);
00857             }
00858         } else if(colonFound != -1) {
00859             ip_address.clear();
00860         }
00861     }
00862 }
00863 
00864 void M2MInterfaceImpl::state_register_address_resolved( EventData *data)
00865 {
00866     tr_debug("M2MInterfaceImpl::state_register_address_resolved");
00867     if(data) {
00868         ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
00869 
00870         sn_nsdl_addr_type_e address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
00871 
00872         M2MInterface::NetworkStack stack = event->_address->_stack;
00873 
00874         if(M2MInterface::LwIP_IPv4 == stack) {
00875             tr_info("M2MInterfaceImpl::state_register_address_resolved : IPv4 address");
00876             address_type = SN_NSDL_ADDRESS_TYPE_IPV4;
00877         } else if((M2MInterface::LwIP_IPv6 == stack) ||
00878                   (M2MInterface::Nanostack_IPv6 == stack)) {
00879             tr_info("M2MInterfaceImpl::state_register_address_resolved : IPv6 address");
00880             address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
00881         }
00882         _connection_handler.start_listening_for_data();
00883         _nsdl_interface.set_server_address((uint8_t*)event->_address->_address,event->_address->_length,
00884                                            event->_port, address_type);
00885         switch (_reconnection_state) {
00886             case M2MInterfaceImpl::None:
00887             case M2MInterfaceImpl::FullRegistration:
00888                 if(!_nsdl_interface.send_register_message()) {
00889                     // If resource creation fails then inform error to application
00890                     tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::MemoryFail");
00891                     internal_event(STATE_IDLE);
00892                     set_error_description(ERROR_REASON_25);
00893                     _observer.error(M2MInterface::MemoryFail);
00894                 }
00895                 break;
00896             case M2MInterfaceImpl::Unregistration:
00897             case M2MInterfaceImpl::WithUpdate:
00898                 // Start registration update in case it is reconnection logic because of network issue.
00899                 internal_event(STATE_UPDATE_REGISTRATION);
00900                 break;
00901         }
00902     }
00903 }
00904 
00905 void M2MInterfaceImpl::state_registered( EventData */*data*/)
00906 {
00907     tr_info("M2MInterfaceImpl::state_registered");
00908     if (_registration_flow_timer) {
00909         _registration_flow_timer->stop_timer();
00910     }
00911     _reconnection_time = _initial_reconnection_time;
00912     _reconnecting = false;
00913 
00914     // Continue with the unregistration process if it has failed due to connection lost
00915     if (_reconnection_state == M2MInterfaceImpl::Unregistration) {
00916         internal_event(STATE_UNREGISTER);
00917     }
00918 
00919     _reconnection_state = M2MInterfaceImpl::None;
00920 }
00921 
00922 void M2MInterfaceImpl::state_update_registration(EventData *data)
00923 {
00924     tr_debug("M2MInterfaceImpl::state_update_registration");
00925     uint32_t lifetime = 0;
00926     bool clear_queue = false;
00927     // Set to false to allow reconnection to work.
00928     _queue_mode_timer_ongoing = false;
00929 
00930     if(data) {
00931         M2MUpdateRegisterData *event = static_cast<M2MUpdateRegisterData *> (data);
00932         // Create new resources if any
00933         if (!event->_object_list.empty()) {
00934             _nsdl_interface.create_nsdl_list_structure(event->_object_list);
00935         }
00936         lifetime = event->_lifetime;
00937     } else {
00938         clear_queue = true;
00939     }
00940 
00941     bool success = _nsdl_interface.send_update_registration(lifetime, clear_queue);
00942     if(!success) {
00943         if(_reconnection_state == M2MInterfaceImpl::WithUpdate) {
00944             if (_reconnection_state != M2MInterfaceImpl::Unregistration) {
00945                 _reconnection_state = M2MInterfaceImpl::FullRegistration;
00946                 if(!_nsdl_interface.send_register_message()) {
00947                     tr_error("M2MInterfaceImpl::state_update_registration : M2MInterface::MemoryFail");
00948                     internal_event(STATE_IDLE);
00949                     set_error_description(ERROR_REASON_25);
00950                     _observer.error(M2MInterface::MemoryFail);
00951                 }
00952             }
00953         }
00954     }
00955 }
00956 
00957 void M2MInterfaceImpl::state_unregister(EventData */*data*/)
00958 {
00959     tr_debug("M2MInterfaceImpl::state_unregister");
00960     internal_event(STATE_SENDING_COAP_DATA);
00961     if(!_nsdl_interface.send_unregister_message()) {
00962         tr_error("M2MInterfaceImpl::state_unregister : M2MInterface::NotRegistered");
00963         internal_event(STATE_IDLE);
00964         set_error_description(ERROR_REASON_16);
00965         _observer.error(M2MInterface::NotRegistered);
00966     }
00967 }
00968 
00969 void M2MInterfaceImpl::state_unregistered( EventData */*data*/)
00970 {
00971     tr_info("M2MInterfaceImpl::state_unregistered");
00972     _reconnection_time = _initial_reconnection_time;
00973     _connection_handler.stop_listening();
00974     internal_event(STATE_IDLE);
00975 }
00976 
00977 void M2MInterfaceImpl::state_sending_coap_data( EventData */*data*/)
00978 {
00979     tr_debug("M2MInterfaceImpl::state_sending_coap_data");
00980     _nsdl_interface.start_nsdl_execution_timer();
00981     internal_event(STATE_WAITING);
00982 }
00983 
00984 void M2MInterfaceImpl::state_coap_data_sent( EventData */*data*/)
00985 {
00986     tr_debug("M2MInterfaceImpl::state_coap_data_sent");
00987     internal_event(STATE_WAITING);
00988 }
00989 
00990 void M2MInterfaceImpl::state_coap_data_received( EventData *data)
00991 {
00992     tr_debug("M2MInterfaceImpl::state_coap_data_received");
00993     if(data) {
00994         ReceivedData *event = static_cast<ReceivedData*> (data);
00995         sn_nsdl_addr_s address;
00996 
00997         M2MInterface::NetworkStack stack = event->_address->_stack;
00998 
00999         if(M2MInterface::LwIP_IPv4 == stack) {
01000             address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
01001             address.addr_len = 4;
01002         } else if((M2MInterface::LwIP_IPv6 == stack) ||
01003                   (M2MInterface::Nanostack_IPv6 == stack)) {
01004             address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
01005             address.addr_len = 16;
01006         }
01007         address.port = event->_address->_port;
01008         address.addr_ptr = (uint8_t*)event->_address->_address;
01009         address.addr_len = event->_address->_length;
01010 
01011         // Process received data
01012         internal_event(STATE_PROCESSING_COAP_DATA);
01013         if(!_nsdl_interface.process_received_data(event->_data,
01014                                                   event->_size,
01015                                                   &address)) {
01016            tr_error("M2MInterfaceImpl::state_coap_data_received : M2MInterface::ResponseParseFailed");
01017            set_error_description(ERROR_REASON_17);
01018             _observer.error(M2MInterface::ResponseParseFailed);
01019         }
01020     }
01021 }
01022 
01023 void M2MInterfaceImpl::state_processing_coap_data( EventData */*data*/)
01024 {
01025     tr_debug("M2MInterfaceImpl::state_processing_coap_data");
01026     internal_event(STATE_WAITING);
01027 }
01028 
01029 void M2MInterfaceImpl::state_coap_data_processed( EventData */*data*/)
01030 {
01031     tr_debug("M2MInterfaceImpl::state_coap_data_processed");
01032     internal_event(STATE_WAITING);
01033 }
01034 
01035 void M2MInterfaceImpl::state_waiting( EventData */*data*/)
01036 {
01037     tr_debug("M2MInterfaceImpl::state_waiting");
01038 }
01039 
01040 // generates an external event. called once per external event
01041 // to start the state machine executing
01042 void M2MInterfaceImpl::external_event(uint8_t new_state,
01043                                      EventData* p_data)
01044 {
01045     tr_debug("M2MInterfaceImpl::external_event : new state %d", new_state);
01046     // if we are supposed to ignore this event
01047     if (new_state == EVENT_IGNORED) {
01048         tr_debug("M2MInterfaceImpl::external_event : new state is EVENT_IGNORED");
01049         _event_ignored = true;
01050     }
01051     else {
01052         tr_debug("M2MInterfaceImpl::external_event : handle new state");
01053         // generate the event and execute the state engine
01054         internal_event(new_state, p_data);
01055     }
01056 }
01057 
01058 // generates an internal event. called from within a state
01059 // function to transition to a new state
01060 void M2MInterfaceImpl::internal_event(uint8_t new_state,
01061                                       EventData* p_data)
01062 {
01063     tr_debug("M2MInterfaceImpl::internal_event : new state %d", new_state);
01064     _event_data = p_data;
01065     _event_generated = true;
01066     _current_state = new_state;
01067     state_engine();
01068 }
01069 
01070 // the state engine executes the state machine states
01071 void M2MInterfaceImpl::state_engine (void)
01072 {
01073     tr_debug("M2MInterfaceImpl::state_engine");
01074     EventData* p_data_temp = NULL;
01075 
01076     // while events are being generated keep executing states
01077     while (_event_generated) {
01078         p_data_temp = _event_data;  // copy of event data pointer
01079         _event_data = NULL;       // event data used up, reset ptr
01080         _event_generated = false;  // event used up, reset flag
01081 
01082         assert(_current_state < _max_states);
01083 
01084         state_function( _current_state, p_data_temp );
01085     }
01086 }
01087 
01088 void M2MInterfaceImpl::state_function( uint8_t current_state, EventData* data )
01089 {
01090     switch( current_state ) {
01091         case STATE_IDLE:
01092             M2MInterfaceImpl::state_idle(data);
01093             break;
01094         case STATE_BOOTSTRAP:
01095         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01096             M2MInterfaceImpl::state_bootstrap(data);
01097         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01098             break;
01099         case STATE_BOOTSTRAP_ADDRESS_RESOLVED:
01100         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01101             M2MInterfaceImpl::state_bootstrap_address_resolved(data);
01102         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01103             break;
01104         case STATE_BOOTSTRAP_RESOURCE_CREATED:
01105         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01106             M2MInterfaceImpl::state_bootstrap_resource_created(data);
01107         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01108             break;
01109         case STATE_BOOTSTRAP_WAIT:
01110         case STATE_BOOTSTRAP_ERROR_WAIT:
01111         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01112             // Do nothing, we're just waiting for data_sent callback
01113         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01114             break;
01115         case STATE_BOOTSTRAPPED:
01116         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01117             M2MInterfaceImpl::state_bootstrapped(data);
01118         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01119             break;
01120         case STATE_REGISTER:
01121             M2MInterfaceImpl::state_register(data);
01122             break;
01123         case STATE_REGISTER_ADDRESS_RESOLVED:
01124             M2MInterfaceImpl::state_register_address_resolved(data);
01125             break;
01126         case STATE_REGISTERED:
01127             M2MInterfaceImpl::state_registered(data);
01128             break;
01129         case STATE_UPDATE_REGISTRATION:
01130             M2MInterfaceImpl::state_update_registration(data);
01131             break;
01132         case STATE_UNREGISTER:
01133             M2MInterfaceImpl::state_unregister(data);
01134             break;
01135         case STATE_UNREGISTERED:
01136             M2MInterfaceImpl::state_unregistered(data);
01137             break;
01138         case STATE_SENDING_COAP_DATA:
01139             M2MInterfaceImpl::state_sending_coap_data(data);
01140             break;
01141         case STATE_COAP_DATA_SENT:
01142             M2MInterfaceImpl::state_coap_data_sent(data);
01143             break;
01144         case STATE_COAP_DATA_RECEIVED:
01145             M2MInterfaceImpl::state_coap_data_received(data);
01146             break;
01147         case STATE_PROCESSING_COAP_DATA:
01148             M2MInterfaceImpl::state_processing_coap_data(data);
01149             break;
01150         case STATE_COAP_DATA_PROCESSED:
01151             M2MInterfaceImpl::state_coap_data_processed(data);
01152             break;
01153         case STATE_WAITING:
01154             M2MInterfaceImpl::state_waiting(data);
01155             break;
01156     }
01157 }
01158 
01159 void M2MInterfaceImpl::start_register_update(M2MUpdateRegisterData *data) {
01160     tr_debug("M2MInterfaceImpl::start_register_update()");
01161     if(!data || (data->_lifetime != 0 && (data->_lifetime < MINIMUM_REGISTRATION_TIME))) {
01162         set_error_description(ERROR_REASON_18);
01163         _observer.error(M2MInterface::InvalidParameters);
01164     }
01165 
01166     if (_reconnecting) {
01167         //If client is in reconnection mode, ignore this call, state machine will reconnect on its own.
01168         return;
01169     }
01170 
01171     _reconnection_state = M2MInterfaceImpl::WithUpdate;
01172     BEGIN_TRANSITION_MAP                                    // - Current State -
01173         TRANSITION_MAP_ENTRY (STATE_REGISTER)                // state_idle
01174         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
01175         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
01176         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
01177         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
01178         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
01179         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
01180         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
01181         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
01182         TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_registered
01183         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
01184         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
01185         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
01186         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
01187         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
01188         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
01189         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
01190         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
01191         TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_waiting
01192     END_TRANSITION_MAP(data)
01193     if(_event_ignored) {
01194         _event_ignored = false;
01195         if (!_reconnecting) {
01196             set_error_description(ERROR_REASON_19);
01197             _observer.error(M2MInterface::NotAllowed);
01198         }
01199     }
01200 }
01201 
01202 void M2MInterfaceImpl::update_endpoint(String &name) {
01203     _nsdl_interface.update_endpoint(name);
01204 }
01205 
01206 void M2MInterfaceImpl::update_domain(String &domain)
01207 {
01208     _nsdl_interface.update_domain(domain);
01209 }
01210 
01211 const String M2MInterfaceImpl::internal_endpoint_name() const
01212 {
01213     return _nsdl_interface.internal_endpoint_name();
01214 }
01215 
01216 const char *M2MInterfaceImpl::error_description() const
01217 {
01218 #ifndef DISABLE_ERROR_DESCRIPTION
01219     return _error_description;
01220 #else
01221     return "";
01222 #endif
01223 }
01224 
01225 void M2MInterfaceImpl::set_error_description(const char *description)
01226 {
01227 #ifndef DISABLE_ERROR_DESCRIPTION
01228     if (strncmp(_error_description, description, sizeof(_error_description)) != 0) {
01229         strncpy(_error_description, description, MAX_ALLOWED_ERROR_STRING_LENGTH - 1);
01230     }
01231 #endif
01232 }
01233 
01234 bool M2MInterfaceImpl::queue_mode() const
01235 {
01236     return (_binding_mode == M2MInterface::UDP_QUEUE ||
01237            _binding_mode == M2MInterface::TCP_QUEUE  ||
01238            _binding_mode == M2MInterface::SMS_QUEUE  ||
01239            _binding_mode == M2MInterface::UDP_SMS_QUEUE);
01240 }
01241 
01242 void M2MInterfaceImpl::get_data_request(const char *uri,
01243                                         const size_t offset,
01244                                         const bool async,
01245                                         get_data_cb data_cb,
01246                                         get_data_error_cb error_cb,
01247                                         void *context)
01248 {
01249     get_data_req_error_e error = FAILED_TO_SEND_MSG;
01250     if(_current_state != STATE_IDLE && uri) {
01251         if (!_nsdl_interface.send_get_data_request(uri, offset, async, data_cb, error_cb, context)) {
01252             error_cb(error, context);
01253         }
01254     }
01255     else {
01256         error_cb(error, context);
01257     }
01258 }
01259