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