leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-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, bool full_registration)
00384 {
00385     tr_error("M2MInterfaceImpl::registration_error code [%d]", error_code);
00386 
00387     _nsdl_interface.set_registration_status(false);
00388 
00389     // Try to register again
00390     if (retry) {
00391         _queue_mode_timer_ongoing = false;
00392 
00393         if (full_registration) {
00394             _reconnection_state = M2MInterfaceImpl::None;
00395         } else if (error_code == M2MInterface::UnregistrationFailed) {
00396             _reconnection_state = M2MInterfaceImpl::Unregistration;
00397         }
00398 
00399         socket_error(M2MConnectionHandler::SOCKET_SEND_ERROR);
00400     } else {
00401         _security = NULL;
00402         internal_event(STATE_IDLE);
00403         if (error_code == M2MInterface::UnregistrationFailed) {
00404             set_error_description(ERROR_REASON_24);
00405         } else {
00406             set_error_description(ERROR_REASON_8);
00407         }
00408         _observer.error((M2MInterface::Error)error_code);
00409     }
00410 }
00411 
00412 void M2MInterfaceImpl::client_unregistered()
00413 {
00414     tr_info("M2MInterfaceImpl::client_unregistered()");
00415     _nsdl_interface.set_registration_status(false);
00416 
00417     // Zero the flag otherwise next registered response will start unregistration process
00418     _reconnection_state = M2MInterfaceImpl::None;
00419 
00420     internal_event(STATE_UNREGISTERED);
00421     //TODO: manage register object in a list.
00422 }
00423 
00424 void M2MInterfaceImpl::bootstrap_done()
00425 {
00426 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00427     tr_info("M2MInterfaceImpl::bootstrap_done");
00428     _reconnection_time = _initial_reconnection_time;
00429     _reconnecting = false;
00430     _reconnection_state = M2MInterfaceImpl::None;
00431     _bootstrapped = true;
00432 
00433     if (_registration_flow_timer) {
00434         _registration_flow_timer->stop_timer();
00435     }
00436 
00437     // Force close connection since either server already closed (sent PEER_CLOSE_NOTIFY)
00438     // or bootstrap flow has finished.
00439     _connection_handler.force_close();
00440 
00441     if (_bootstrap_finished) {
00442         // Inform to observer only if bootstrap has already been finished
00443         // This has to be done like this since we might get bootstrap_done
00444         // callback BEFORE bootstrap_finish
00445         internal_event(STATE_BOOTSTRAPPED);
00446         _observer.bootstrap_done(_nsdl_interface.get_security_object());
00447     }
00448 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00449 }
00450 
00451 void M2MInterfaceImpl::bootstrap_finish()
00452 {
00453 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00454     tr_info("M2MInterfaceImpl::bootstrap_finish");
00455     internal_event(STATE_BOOTSTRAP_WAIT);
00456     _observer.bootstrap_data_ready(_nsdl_interface.get_security_object());
00457     _bootstrap_finished = true;
00458 
00459     if (_bootstrapped) {
00460         // If _bootstrapped is set, we have already received the bootstrap_done
00461         // callback so we must inform observer now
00462         bootstrap_done();
00463     }
00464 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00465 }
00466 
00467 void M2MInterfaceImpl::bootstrap_wait()
00468 {
00469 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00470     tr_info("M2MInterfaceImpl::bootstrap_wait");
00471     internal_event(STATE_BOOTSTRAP_WAIT);
00472 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00473 }
00474 
00475 void M2MInterfaceImpl::bootstrap_error_wait(const char *reason)
00476 {
00477 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00478     tr_error("M2MInterfaceImpl::bootstrap_error_wait");
00479     set_error_description(reason);
00480     internal_event(STATE_BOOTSTRAP_ERROR_WAIT);
00481 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00482 }
00483 
00484 void M2MInterfaceImpl::bootstrap_error(const char *reason)
00485 {
00486 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00487     tr_error("M2MInterfaceImpl::bootstrap_error(%s)", reason);
00488     _bootstrapped = false;
00489     if (_registration_flow_timer) {
00490         _registration_flow_timer->stop_timer();
00491     }
00492 
00493     _reconnection_state = M2MInterfaceImpl::None;
00494 
00495     set_error_description(reason);
00496 
00497     _observer.error(M2MInterface::BootstrapFailed);
00498 
00499     internal_event(STATE_IDLE);
00500     _reconnecting = true;
00501     _connection_handler.stop_listening();
00502 
00503     _retry_timer_expired = false;
00504     _retry_timer.start_timer(_reconnection_time * 1000,
00505                               M2MTimerObserver::RetryTimer);
00506     tr_info("M2MInterfaceImpl::bootstrap_error - reconnecting in %" PRIu64 "(s)", _reconnection_time);
00507     _reconnection_time = _reconnection_time * RECONNECT_INCREMENT_FACTOR;
00508     if(_reconnection_time >= MAX_RECONNECT_TIMEOUT) {
00509         _reconnection_time = MAX_RECONNECT_TIMEOUT;
00510     }
00511 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00512 }
00513 
00514 void M2MInterfaceImpl::coap_data_processed()
00515 {
00516     tr_debug("M2MInterfaceImpl::coap_data_processed()");
00517     internal_event(STATE_COAP_DATA_PROCESSED);
00518 }
00519 
00520 void M2MInterfaceImpl::value_updated(M2MBase *base)
00521 {
00522     tr_debug("M2MInterfaceImpl::value_updated");
00523     if(base) {
00524         M2MBase::BaseType type = base->base_type();
00525         _observer.value_updated(base, type);
00526     }
00527 }
00528 
00529 void M2MInterfaceImpl::data_available(uint8_t* data,
00530                                       uint16_t data_size,
00531                                       const M2MConnectionObserver::SocketAddress &address)
00532 {
00533     tr_debug("M2MInterfaceImpl::data_available");
00534     ReceivedData event;
00535     event._data = data;
00536     event._size = data_size;
00537     event._address = &address;
00538     internal_event(STATE_COAP_DATA_RECEIVED, &event);
00539 }
00540 
00541 void M2MInterfaceImpl::socket_error(int error_code, bool retry)
00542 {
00543     // Bootstrap completed once PEER CLOSE notify received from the server.
00544     if (_current_state == STATE_BOOTSTRAP_WAIT &&
00545         error_code == M2MConnectionHandler::SSL_PEER_CLOSE_NOTIFY) {
00546         _security = NULL;
00547         bootstrap_done();
00548         return;
00549     }
00550 
00551     tr_error("M2MInterfaceImpl::socket_error: (%d), retry (%d), reconnecting (%d), reconnection_state (%d)",
00552              error_code, retry, _reconnecting, (int)_reconnection_state);
00553 
00554     // Ignore errors while client is sleeping
00555     if (queue_mode()) {
00556         if (_callback_handler && _queue_mode_timer_ongoing) {
00557             tr_info("M2MInterfaceImpl::socket_error - Queue Mode - don't try to reconnect while in QueueMode");
00558             return;
00559         }
00560     }
00561     _queue_sleep_timer.stop_timer();
00562 
00563     if (_registration_flow_timer) {
00564         _registration_flow_timer->stop_timer();
00565     }
00566 
00567     const char *error_code_des;
00568     M2MInterface::Error error = M2MInterface::ErrorNone;
00569     switch (error_code) {
00570         case M2MConnectionHandler::SSL_CONNECTION_ERROR:
00571             error = M2MInterface::SecureConnectionFailed;
00572             error_code_des = ERROR_SECURE_CONNECTION;
00573             break;
00574         case M2MConnectionHandler::DNS_RESOLVING_ERROR:
00575             error = M2MInterface::DnsResolvingFailed;
00576             error_code_des = ERROR_DNS;
00577             break;
00578         case M2MConnectionHandler::SOCKET_READ_ERROR:
00579             error = M2MInterface::NetworkError;
00580             error_code_des = ERROR_NETWORK;
00581             break;
00582         case M2MConnectionHandler::SOCKET_SEND_ERROR:
00583             error = M2MInterface::NetworkError;
00584             error_code_des = ERROR_NETWORK;
00585             break;
00586         case M2MConnectionHandler::SSL_HANDSHAKE_ERROR:
00587             error = M2MInterface::SecureConnectionFailed;
00588             error_code_des = ERROR_SECURE_CONNECTION;
00589             break;
00590         case M2MConnectionHandler::SOCKET_ABORT:
00591             error = M2MInterface::NetworkError;
00592             error_code_des = ERROR_NETWORK;
00593             break;
00594         case M2MConnectionHandler::MEMORY_ALLOCATION_FAILED:
00595             error = M2MInterface::MemoryFail;
00596             error_code_des = ERROR_NO_MEMORY;
00597             break;
00598         case M2MConnectionHandler::FAILED_TO_READ_CREDENTIALS:
00599             error = M2MInterface::FailedToReadCredentials;
00600             error_code_des = ERROR_FAILED_TO_READ_CREDENTIALS;
00601             break;
00602         default:
00603             error_code_des = ERROR_NO;
00604             break;
00605     }
00606 
00607     internal_event(STATE_IDLE);
00608 
00609     // Do a reconnect
00610     if (retry) {
00611         if ((error == M2MInterface::SecureConnectionFailed || error == M2MInterface::InvalidParameters) &&
00612              _bootstrapped) {
00613             // Connector client will start the bootstrap flow again
00614             tr_info("M2MInterfaceImpl::socket_error - goes to re-bootstrap");
00615             _observer.error(M2MInterface::SecureConnectionFailed);
00616             return;
00617         }
00618 
00619         _nsdl_interface.set_request_context_to_be_resend(NULL, 0);
00620         _reconnecting = true;
00621         _connection_handler.stop_listening();
00622         _retry_timer_expired = false;
00623         _retry_timer.start_timer(_reconnection_time * 1000,
00624                                  M2MTimerObserver::RetryTimer);
00625 
00626         tr_info("M2MInterfaceImpl::socket_error - reconnecting in %" PRIu64 "(s)", _reconnection_time);
00627 
00628         _reconnection_time = _reconnection_time * RECONNECT_INCREMENT_FACTOR;
00629         if (_reconnection_time >= MAX_RECONNECT_TIMEOUT) {
00630             _reconnection_time = MAX_RECONNECT_TIMEOUT;
00631         }
00632 #ifndef DISABLE_ERROR_DESCRIPTION
00633         snprintf(_error_description, sizeof(_error_description), ERROR_REASON_9, error_code_des);
00634 #endif
00635     }
00636     // Inform application
00637     if (!retry && M2MInterface::ErrorNone != error) {
00638         tr_info("M2MInterfaceImpl::socket_error - send error to application");
00639         _connection_handler.stop_listening();
00640         _retry_timer.stop_timer();
00641         _security = NULL;
00642         _reconnecting = false;
00643         _reconnection_time = _initial_reconnection_time;
00644         _reconnection_state = M2MInterfaceImpl::None;
00645 #ifndef DISABLE_ERROR_DESCRIPTION
00646         snprintf(_error_description, sizeof(_error_description), ERROR_REASON_10, error_code_des);
00647 #endif
00648     }
00649     if (M2MInterface::ErrorNone != error) {
00650         _observer.error(error);
00651     }
00652 }
00653 
00654 void M2MInterfaceImpl::address_ready(const M2MConnectionObserver::SocketAddress &address,
00655                                      M2MConnectionObserver::ServerType server_type,
00656                                      const uint16_t server_port)
00657 {
00658     tr_debug("M2MInterfaceImpl::address_ready");
00659     ResolvedAddressData data;
00660     data._address = &address;
00661     data._port = server_port;
00662     if( M2MConnectionObserver::Bootstrap == server_type) {
00663         tr_info("M2MInterfaceImpl::address_ready() Server Type Bootstrap");
00664         internal_event(STATE_BOOTSTRAP_ADDRESS_RESOLVED, &data);
00665     } else {
00666         tr_info("M2MInterfaceImpl::address_ready() Server Type LWM2M");
00667         internal_event(STATE_REGISTER_ADDRESS_RESOLVED, &data);
00668     }
00669 }
00670 
00671 void M2MInterfaceImpl::data_sent()
00672 {
00673     tr_debug("M2MInterfaceImpl::data_sent()");
00674     if(queue_mode()) {
00675         if(_callback_handler && (_nsdl_interface.is_unregister_ongoing() == false)) {
00676             _queue_sleep_timer.stop_timer();
00677             _queue_sleep_timer.start_timer(_nsdl_interface.total_retransmission_time(_nsdl_interface.get_resend_count()) * (uint64_t)1000,
00678                                             M2MTimerObserver::QueueSleep);
00679         }
00680     }
00681 
00682     if (_current_state == STATE_BOOTSTRAP_ERROR_WAIT) {
00683         // bootstrap_error to be called only after we have sent the last ACK.
00684         // Otherwise client will goto reconnection mode before ACK has sent.
00685         bootstrap_error(error_description());
00686     } else if (_current_state != STATE_BOOTSTRAP_WAIT) {
00687         internal_event(STATE_COAP_DATA_SENT);
00688     }
00689 
00690     // Delay the time when CoAP ping will be send.
00691     _nsdl_interface.calculate_new_coap_ping_send_time();
00692 }
00693 
00694 void M2MInterfaceImpl::timer_expired(M2MTimerObserver::Type type)
00695 {
00696     if (M2MTimerObserver::QueueSleep == type) {
00697         if (_reconnecting) {
00698             tr_debug("M2MInterfaceImpl::timer_expired() - reconnection ongoing, continue sleep timer");
00699             _queue_sleep_timer.start_timer(_nsdl_interface.total_retransmission_time(_nsdl_interface.get_resend_count()) * (uint64_t)1000,
00700                                             M2MTimerObserver::QueueSleep);
00701         } else {
00702             tr_debug("M2MInterfaceImpl::timer_expired() - sleep");
00703             M2MTimer &timer = _nsdl_interface.get_nsdl_execution_timer();
00704             timer.stop_timer();
00705             _queue_mode_timer_ongoing = true;
00706             if(_callback_handler) {
00707                 _callback_handler();
00708             }
00709         }
00710     } else if (M2MTimerObserver::RetryTimer == type) {
00711         tr_debug("M2MInterfaceImpl::timer_expired() - retry");
00712         _retry_timer_expired = true;
00713         if (_bootstrapped) {
00714             internal_event(STATE_REGISTER);
00715         } else {
00716             internal_event(STATE_BOOTSTRAP);
00717         }
00718     } else if (M2MTimerObserver::BootstrapFlowTimer == type) {
00719 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00720         tr_debug("M2MInterfaceImpl::timer_expired() - bootstrap");
00721         _bootstrapped = false;
00722         if (_registration_flow_timer) {
00723             _registration_flow_timer->stop_timer();
00724         }
00725         bootstrap_error(ERROR_REASON_23);
00726 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00727     } else if (M2MTimerObserver::RegistrationFlowTimer == type) {
00728         tr_debug("M2MInterfaceImpl::timer_expired() - register");
00729         registration_error(M2MInterface::Timeout, true);
00730     }
00731 }
00732 
00733 // state machine sits here.
00734 void M2MInterfaceImpl::state_idle(EventData* /*data*/)
00735 {
00736     tr_debug("M2MInterfaceImpl::state_idle");
00737     _nsdl_interface.stop_timers();
00738     _nsdl_interface.clear_sent_blockwise_messages();
00739     _nsdl_interface.clear_received_blockwise_messages();
00740     _queue_sleep_timer.stop_timer();
00741 }
00742 
00743 void M2MInterfaceImpl::state_bootstrap(EventData *data)
00744 {
00745 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00746     tr_debug("M2MInterfaceImpl::state_bootstrap");
00747     // Start with bootstrapping preparation
00748     _bootstrapped = false;
00749     _bootstrap_finished = false;
00750     _nsdl_interface.set_registration_status(false);
00751     M2MSecurityData *event = static_cast<M2MSecurityData *> (data);
00752     if(!_security) {
00753         M2MInterface::Error error = M2MInterface::InvalidParameters;
00754         if (event) {
00755             _security = event->_object;
00756             if(_security) {
00757                 int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap);
00758                 tr_info("M2MInterfaceImpl::state_bootstrap - bs_id = %" PRId32 "(s)", bs_id);
00759                 if(bs_id >= 0) {
00760                     String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri, bs_id);
00761                     _nsdl_interface.set_server_address(server_address.c_str());
00762                     tr_info("M2MInterfaceImpl::state_bootstrap - server_address %s", server_address.c_str());
00763                     String coap;
00764                     if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
00765                          coap = COAP;
00766                     }
00767                     else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
00768                         _security->resource_value_int(M2MSecurity::SecurityMode, bs_id) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
00769                     }
00770                     if(!coap.empty()) {
00771                         server_address = server_address.substr(coap.size(),
00772                                                            server_address.size()-coap.size());
00773 
00774                         process_address(server_address, _server_ip_address, _server_port);
00775 
00776                         tr_info("M2MInterfaceImpl::state_bootstrap - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00777                         // If bind and resolving server address succeed then proceed else
00778                         // return error to the application and go to Idle state.
00779                         if(!_server_ip_address.empty()) {
00780                             error = M2MInterface::ErrorNone;
00781                             if (_registration_flow_timer) {
00782                                 _registration_flow_timer->stop_timer();
00783                                 _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00784                                                               M2MTimerObserver::BootstrapFlowTimer);
00785                             }
00786                             _connection_handler.resolve_server_address(_server_ip_address,
00787                                                                         _server_port,
00788                                                                         M2MConnectionObserver::Bootstrap,
00789                                                                         _security);
00790                         }
00791                     }
00792                 }
00793             }
00794         }
00795         if (error != M2MInterface::ErrorNone) {
00796             tr_error("M2MInterfaceImpl::state_bootstrap - set error as M2MInterface::InvalidParameters");
00797             internal_event(STATE_IDLE);
00798             set_error_description(ERROR_REASON_11);
00799             _observer.error(error);
00800         }
00801     } else {
00802         _listen_port = 0;
00803         _connection_handler.bind_connection(_listen_port);
00804         if (_registration_flow_timer) {
00805             _registration_flow_timer->stop_timer();
00806             _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00807                                           M2MTimerObserver::BootstrapFlowTimer);
00808         }
00809         tr_info("M2MInterfaceImpl::state_bootstrap (reconnect) - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00810         _connection_handler.resolve_server_address(_server_ip_address,
00811                                                     _server_port,
00812                                                     M2MConnectionObserver::Bootstrap,
00813                                                     _security);
00814     }
00815 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00816 }
00817 
00818 void M2MInterfaceImpl::state_bootstrap_address_resolved( EventData *data)
00819 {
00820 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00821     tr_debug("M2MInterfaceImpl::state_bootstrap_address_resolved");
00822     if (data) {
00823         ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
00824         sn_nsdl_addr_s address;
00825 
00826         M2MInterface::NetworkStack stack = event->_address->_stack;
00827 
00828         if(M2MInterface::LwIP_IPv4 == stack) {
00829             tr_info("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv4 address");
00830             address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
00831         } else if((M2MInterface::LwIP_IPv6 == stack) ||
00832                   (M2MInterface::Nanostack_IPv6 == stack)) {
00833             tr_info("M2MInterfaceImpl::state_bootstrap_address_resolved : IPv6 address");
00834             address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
00835         }
00836         address.port = event->_port;
00837         address.addr_ptr = (uint8_t*)event->_address->_address;
00838         address.addr_len = event->_address->_length;
00839         _connection_handler.start_listening_for_data();
00840 
00841         if(_nsdl_interface.create_bootstrap_resource(&address)) {
00842            internal_event(STATE_BOOTSTRAP_RESOURCE_CREATED);
00843         } else{
00844             // If resource creation fails then inform error to application
00845             tr_error("M2MInterfaceImpl::state_bootstrap_address_resolved : M2MInterface::InvalidParameters");
00846             internal_event(STATE_IDLE);
00847             set_error_description(ERROR_REASON_12);
00848             _observer.error(M2MInterface::InvalidParameters);
00849         }
00850     }
00851 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00852 }
00853 
00854 void M2MInterfaceImpl::state_bootstrap_resource_created( EventData */*data*/)
00855 {
00856 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00857     tr_debug("M2MInterfaceImpl::state_bootstrap_resource_created");
00858 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00859 }
00860 
00861 void M2MInterfaceImpl::state_bootstrapped( EventData */*data*/)
00862 {
00863 #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00864     tr_debug("M2MInterfaceImpl::state_bootstrapped");
00865 #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
00866 }
00867 
00868 void M2MInterfaceImpl::state_register(EventData *data)
00869 {
00870     tr_debug("M2MInterfaceImpl::state_register");
00871     _nsdl_interface.set_registration_status(false);
00872     M2MRegisterData *event = static_cast<M2MRegisterData *> (data);
00873     if (!_security) {
00874         M2MInterface::Error error = M2MInterface::InvalidParameters;
00875         // Start with registration preparation
00876         if(event) {
00877             _security = event->_object;
00878             if(_security) {
00879                 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer);
00880                 if(m2m_id >= 0) {
00881                     if(_nsdl_interface.create_nsdl_list_structure(event->_base_list)) {
00882                         // If the nsdl resource structure is created successfully
00883                         String server_address = _security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id);
00884                         _nsdl_interface.set_server_address(server_address.c_str());
00885                         tr_info("M2MInterfaceImpl::state_register - server_address %s", server_address.c_str());
00886                         String  coap;
00887                         if(server_address.compare(0,sizeof(COAP)-1,COAP) == 0) {
00888                              coap = COAP;
00889                         }
00890                         else if(server_address.compare(0,sizeof(COAPS)-1,COAPS) == 0) {
00891                             _security->resource_value_int(M2MSecurity::SecurityMode, m2m_id) != M2MSecurity::NoSecurity ? coap = COAPS: coap = "";
00892                         }
00893                         if(!coap.empty()) {
00894                             server_address = server_address.substr(coap.size(),
00895                                                                server_address.size() - coap.size());
00896                             process_address(server_address, _server_ip_address, _server_port);
00897 
00898                             tr_info("M2MInterfaceImpl::state_register - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00899                             if(!_server_ip_address.empty()) {
00900                                 // Connection related errors are coming through callback
00901                                 if (_registration_flow_timer) {
00902                                     _registration_flow_timer->stop_timer();
00903                                     _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00904                                                                   M2MTimerObserver::RegistrationFlowTimer);
00905                                 }
00906                                 error = M2MInterface::ErrorNone;
00907                                 _connection_handler.resolve_server_address(_server_ip_address,_server_port,
00908                                                                             M2MConnectionObserver::LWM2MServer,
00909                                                                             _security);
00910                             }
00911                         }
00912                     } else {
00913                         tr_error("M2MInterfaceImpl::state_register - fail to create nsdl list structure!");
00914                     }
00915                 }
00916             }
00917         }
00918         if (error != M2MInterface::ErrorNone) {
00919             tr_error("M2MInterfaceImpl::state_register - set error as M2MInterface::InvalidParameters");
00920             internal_event(STATE_IDLE);
00921             set_error_description(ERROR_REASON_13);
00922             _observer.error(error);
00923         }
00924     } else {
00925         _listen_port = 0;
00926         if (event) {
00927             _nsdl_interface.create_nsdl_list_structure(event->_base_list);
00928         }
00929         _connection_handler.bind_connection(_listen_port);
00930         if (_registration_flow_timer) {
00931             _registration_flow_timer->stop_timer();
00932             _registration_flow_timer->start_timer(MBED_CLIENT_RECONNECTION_COUNT * MBED_CLIENT_RECONNECTION_INTERVAL * 8 * 1000,
00933                                           M2MTimerObserver::RegistrationFlowTimer);
00934         }
00935         tr_info("M2MInterfaceImpl::state_register (reconnect) - IP address %s, Port %d", _server_ip_address.c_str(), _server_port);
00936         _connection_handler.resolve_server_address(_server_ip_address,_server_port,
00937                                                     M2MConnectionObserver::LWM2MServer,
00938                                                     _security);
00939     }
00940 }
00941 
00942 void M2MInterfaceImpl::process_address(const String& server_address, String& ip_address, uint16_t& port) {
00943 
00944     int colonFound = server_address.find_last_of(':'); //10
00945     if(colonFound != -1) {
00946         ip_address = server_address.substr(0,colonFound);
00947         port = atoi(server_address.substr(colonFound+1,
00948                                          server_address.size()-ip_address.size()).c_str());
00949         colonFound = ip_address.find_last_of(']');
00950         if(ip_address.compare(0,1,"[") == 0) {
00951             if(colonFound == -1) {
00952                 ip_address.clear();
00953             } else {
00954                 ip_address = ip_address.substr(1,colonFound-1);
00955             }
00956         } else if(colonFound != -1) {
00957             ip_address.clear();
00958         }
00959     }
00960 }
00961 
00962 void M2MInterfaceImpl::state_register_address_resolved( EventData *data)
00963 {
00964     tr_debug("M2MInterfaceImpl::state_register_address_resolved - reconnect status %d", _reconnection_state);
00965     if(data) {
00966         ResolvedAddressData *event = static_cast<ResolvedAddressData *> (data);
00967 
00968         sn_nsdl_addr_type_e address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
00969 
00970         M2MInterface::NetworkStack stack = event->_address->_stack;
00971 
00972         if(M2MInterface::LwIP_IPv4 == stack) {
00973             tr_info("M2MInterfaceImpl::state_register_address_resolved : IPv4 address");
00974             address_type = SN_NSDL_ADDRESS_TYPE_IPV4;
00975         } else if((M2MInterface::LwIP_IPv6 == stack) ||
00976                   (M2MInterface::Nanostack_IPv6 == stack)) {
00977             tr_info("M2MInterfaceImpl::state_register_address_resolved : IPv6 address");
00978             address_type = SN_NSDL_ADDRESS_TYPE_IPV6;
00979         }
00980         _connection_handler.start_listening_for_data();
00981         _nsdl_interface.set_server_address((uint8_t*)event->_address->_address,event->_address->_length,
00982                                            event->_port, address_type);
00983         switch (_reconnection_state) {
00984             case M2MInterfaceImpl::None:
00985                 if (!_nsdl_interface.send_register_message()) {
00986                     // If resource creation fails then inform error to application
00987                     tr_error("M2MInterfaceImpl::state_register_address_resolved : M2MInterface::MemoryFail");
00988                     internal_event(STATE_IDLE);
00989                     set_error_description(ERROR_REASON_25);
00990                     _observer.error(M2MInterface::MemoryFail);
00991                 }
00992                 break;
00993             case M2MInterfaceImpl::Unregistration:
00994             case M2MInterfaceImpl::WithUpdate:
00995                 // Start registration update in case it is reconnection logic because of network issue.
00996                 internal_event(STATE_UPDATE_REGISTRATION);
00997                 break;
00998         }
00999     }
01000 }
01001 
01002 void M2MInterfaceImpl::state_registered( EventData */*data*/)
01003 {
01004     tr_info("M2MInterfaceImpl::state_registered");
01005     if (_registration_flow_timer) {
01006         _registration_flow_timer->stop_timer();
01007     }
01008     _reconnection_time = _initial_reconnection_time;
01009     _reconnecting = false;
01010     _nsdl_interface.set_registration_status(true);
01011     // Continue with the unregistration process if it has failed due to connection lost
01012     if (_reconnection_state == M2MInterfaceImpl::Unregistration) {
01013         internal_event(STATE_UNREGISTER);
01014     } else {
01015         _reconnection_state = M2MInterfaceImpl::WithUpdate;
01016     }
01017 }
01018 
01019 void M2MInterfaceImpl::state_update_registration(EventData *data)
01020 {
01021     tr_debug("M2MInterfaceImpl::state_update_registration");
01022     uint32_t lifetime = 0;
01023     // Set to false to allow reconnection to work.
01024     _queue_mode_timer_ongoing = false;
01025 
01026     if (data) {
01027         M2MUpdateRegisterData *event = static_cast<M2MUpdateRegisterData *> (data);
01028         // Create new resources if any
01029         if (!event->_base_list.empty()) {
01030             _nsdl_interface.create_nsdl_list_structure(event->_base_list);
01031         }
01032         lifetime = event->_lifetime;
01033     }
01034 
01035     bool success = _nsdl_interface.send_update_registration(lifetime);
01036     if (!success) {
01037         tr_error("M2MInterfaceImpl::state_update_registration : M2MInterface::MemoryFail");
01038         internal_event(STATE_IDLE);
01039         set_error_description(ERROR_REASON_25);
01040         _observer.error(M2MInterface::MemoryFail);
01041     }
01042 }
01043 
01044 void M2MInterfaceImpl::state_unregister(EventData */*data*/)
01045 {
01046     tr_debug("M2MInterfaceImpl::state_unregister");
01047     internal_event(STATE_SENDING_COAP_DATA);
01048     if(!_nsdl_interface.send_unregister_message()) {
01049         tr_error("M2MInterfaceImpl::state_unregister : M2MInterface::NotRegistered");
01050         internal_event(STATE_IDLE);
01051         set_error_description(ERROR_REASON_16);
01052         _observer.error(M2MInterface::NotRegistered);
01053     }
01054 }
01055 
01056 void M2MInterfaceImpl::state_unregistered( EventData */*data*/)
01057 {
01058     tr_info("M2MInterfaceImpl::state_unregistered");
01059     _reconnection_time = _initial_reconnection_time;
01060     _connection_handler.force_close();
01061     _security = NULL;
01062     _observer.object_unregistered(_register_server);
01063     internal_event(STATE_IDLE);
01064 }
01065 
01066 void M2MInterfaceImpl::state_sending_coap_data( EventData */*data*/)
01067 {
01068     tr_debug("M2MInterfaceImpl::state_sending_coap_data");
01069     _nsdl_interface.start_nsdl_execution_timer();
01070     internal_event(STATE_WAITING);
01071 }
01072 
01073 void M2MInterfaceImpl::state_coap_data_sent( EventData */*data*/)
01074 {
01075     tr_debug("M2MInterfaceImpl::state_coap_data_sent");
01076     internal_event(STATE_WAITING);
01077 }
01078 
01079 void M2MInterfaceImpl::state_coap_data_received(EventData *data)
01080 {
01081     tr_debug("M2MInterfaceImpl::state_coap_data_received");
01082     if(data) {
01083         ReceivedData *event = static_cast<ReceivedData*> (data);
01084         sn_nsdl_addr_s address;
01085 
01086         M2MInterface::NetworkStack stack = event->_address->_stack;
01087 
01088         if(M2MInterface::LwIP_IPv4 == stack) {
01089             address.type = SN_NSDL_ADDRESS_TYPE_IPV4;
01090             address.addr_len = 4;
01091         } else if((M2MInterface::LwIP_IPv6 == stack) ||
01092                   (M2MInterface::Nanostack_IPv6 == stack)) {
01093             address.type = SN_NSDL_ADDRESS_TYPE_IPV6;
01094             address.addr_len = 16;
01095         }
01096         address.port = event->_address->_port;
01097         address.addr_ptr = (uint8_t*)event->_address->_address;
01098         address.addr_len = event->_address->_length;
01099 
01100         // Process received data
01101         internal_event(STATE_PROCESSING_COAP_DATA);
01102         if(!_nsdl_interface.process_received_data(event->_data,
01103                                                   event->_size,
01104                                                   &address)) {
01105            tr_error("M2MInterfaceImpl::state_coap_data_received : M2MInterface::ResponseParseFailed");
01106            set_error_description(ERROR_REASON_17);
01107             _observer.error(M2MInterface::ResponseParseFailed);
01108         }
01109     }
01110 }
01111 
01112 void M2MInterfaceImpl::state_processing_coap_data( EventData */*data*/)
01113 {
01114     tr_debug("M2MInterfaceImpl::state_processing_coap_data");
01115     internal_event(STATE_WAITING);
01116 }
01117 
01118 void M2MInterfaceImpl::state_coap_data_processed( EventData */*data*/)
01119 {
01120     tr_debug("M2MInterfaceImpl::state_coap_data_processed");
01121     internal_event(STATE_WAITING);
01122 }
01123 
01124 void M2MInterfaceImpl::state_waiting( EventData */*data*/)
01125 {
01126     tr_debug("M2MInterfaceImpl::state_waiting");
01127 }
01128 
01129 // generates an external event. called once per external event
01130 // to start the state machine executing
01131 void M2MInterfaceImpl::external_event(uint8_t new_state,
01132                                      EventData* p_data)
01133 {
01134     tr_debug("M2MInterfaceImpl::external_event : new state %d", new_state);
01135     // if we are supposed to ignore this event
01136     if (new_state == EVENT_IGNORED) {
01137         tr_debug("M2MInterfaceImpl::external_event : new state is EVENT_IGNORED");
01138         _event_ignored = true;
01139     }
01140     else {
01141         tr_debug("M2MInterfaceImpl::external_event : handle new state");
01142         // generate the event and execute the state engine
01143         internal_event(new_state, p_data);
01144     }
01145 }
01146 
01147 // generates an internal event. called from within a state
01148 // function to transition to a new state
01149 void M2MInterfaceImpl::internal_event(uint8_t new_state,
01150                                       EventData* p_data)
01151 {
01152     tr_debug("M2MInterfaceImpl::internal_event : new state %d", new_state);
01153     _event_data = p_data;
01154     _event_generated = true;
01155     _current_state = new_state;
01156     state_engine();
01157 }
01158 
01159 // the state engine executes the state machine states
01160 void M2MInterfaceImpl::state_engine (void)
01161 {
01162     tr_debug("M2MInterfaceImpl::state_engine");
01163     EventData* p_data_temp = NULL;
01164 
01165     // while events are being generated keep executing states
01166     while (_event_generated) {
01167         p_data_temp = _event_data;  // copy of event data pointer
01168         _event_data = NULL;       // event data used up, reset ptr
01169         _event_generated = false;  // event used up, reset flag
01170 
01171         assert(_current_state < _max_states);
01172 
01173         state_function( _current_state, p_data_temp );
01174     }
01175 }
01176 
01177 void M2MInterfaceImpl::state_function( uint8_t current_state, EventData* data )
01178 {
01179     switch( current_state ) {
01180         case STATE_IDLE:
01181             M2MInterfaceImpl::state_idle(data);
01182             break;
01183         case STATE_BOOTSTRAP:
01184         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01185             M2MInterfaceImpl::state_bootstrap(data);
01186         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01187             break;
01188         case STATE_BOOTSTRAP_ADDRESS_RESOLVED:
01189         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01190             M2MInterfaceImpl::state_bootstrap_address_resolved(data);
01191         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01192             break;
01193         case STATE_BOOTSTRAP_RESOURCE_CREATED:
01194         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01195             M2MInterfaceImpl::state_bootstrap_resource_created(data);
01196         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01197             break;
01198         case STATE_BOOTSTRAP_WAIT:
01199         case STATE_BOOTSTRAP_ERROR_WAIT:
01200         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01201             // Do nothing, we're just waiting for data_sent callback
01202         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01203             break;
01204         case STATE_BOOTSTRAPPED:
01205         #ifndef MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01206             M2MInterfaceImpl::state_bootstrapped(data);
01207         #endif //MBED_CLIENT_DISABLE_BOOTSTRAP_FEATURE
01208             break;
01209         case STATE_REGISTER:
01210             M2MInterfaceImpl::state_register(data);
01211             break;
01212         case STATE_REGISTER_ADDRESS_RESOLVED:
01213             M2MInterfaceImpl::state_register_address_resolved(data);
01214             break;
01215         case STATE_REGISTERED:
01216             M2MInterfaceImpl::state_registered(data);
01217             break;
01218         case STATE_UPDATE_REGISTRATION:
01219             M2MInterfaceImpl::state_update_registration(data);
01220             break;
01221         case STATE_UNREGISTER:
01222             M2MInterfaceImpl::state_unregister(data);
01223             break;
01224         case STATE_UNREGISTERED:
01225             M2MInterfaceImpl::state_unregistered(data);
01226             break;
01227         case STATE_SENDING_COAP_DATA:
01228             M2MInterfaceImpl::state_sending_coap_data(data);
01229             break;
01230         case STATE_COAP_DATA_SENT:
01231             M2MInterfaceImpl::state_coap_data_sent(data);
01232             break;
01233         case STATE_COAP_DATA_RECEIVED:
01234             M2MInterfaceImpl::state_coap_data_received(data);
01235             break;
01236         case STATE_PROCESSING_COAP_DATA:
01237             M2MInterfaceImpl::state_processing_coap_data(data);
01238             break;
01239         case STATE_COAP_DATA_PROCESSED:
01240             M2MInterfaceImpl::state_coap_data_processed(data);
01241             break;
01242         case STATE_WAITING:
01243             M2MInterfaceImpl::state_waiting(data);
01244             break;
01245     }
01246 }
01247 
01248 void M2MInterfaceImpl::start_register_update(M2MUpdateRegisterData *data) {
01249     tr_debug("M2MInterfaceImpl::start_register_update()");
01250     if(!data || (data->_lifetime != 0 && (data->_lifetime < MINIMUM_REGISTRATION_TIME))) {
01251         set_error_description(ERROR_REASON_18);
01252         _observer.error(M2MInterface::InvalidParameters);
01253     }
01254 
01255     if (_reconnecting) {
01256         //If client is in reconnection mode, ignore this call, state machine will reconnect on its own.
01257         return;
01258     } else if (_nsdl_interface.is_update_register_ongoing()) {
01259         set_error_description(ERROR_REASON_27);
01260         _observer.error(M2MInterface::NotAllowed);
01261         return;
01262     }
01263 
01264     _reconnection_state = M2MInterfaceImpl::WithUpdate;
01265     BEGIN_TRANSITION_MAP                                    // - Current State -
01266         TRANSITION_MAP_ENTRY (STATE_REGISTER)                // state_idle
01267         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap
01268         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state__bootstrap_address_resolved
01269         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_resource_created
01270         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_wait
01271         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrap_error_wait
01272         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_bootstrapped
01273         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register
01274         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_register_address_resolved
01275         TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_registered
01276         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_update_registration
01277         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregister
01278         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_unregistered
01279         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_sending_coap_data
01280         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_sent
01281         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_received
01282         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_processing_coap_data
01283         TRANSITION_MAP_ENTRY (EVENT_IGNORED)                // state_coap_data_processed
01284         TRANSITION_MAP_ENTRY (STATE_UPDATE_REGISTRATION)    // state_waiting
01285     END_TRANSITION_MAP(data)
01286     if(_event_ignored) {
01287         _event_ignored = false;
01288         if (!_reconnecting) {
01289             set_error_description(ERROR_REASON_19);
01290             _observer.error(M2MInterface::NotAllowed);
01291         }
01292     }
01293 }
01294 
01295 bool M2MInterfaceImpl::remove_object(M2MBase *object)
01296 {
01297     return _nsdl_interface.remove_object_from_list(object);
01298 }
01299 
01300 void M2MInterfaceImpl::update_endpoint(const String &name) {
01301     _nsdl_interface.update_endpoint(name);
01302 }
01303 
01304 void M2MInterfaceImpl::update_domain(const String &domain)
01305 {
01306     _nsdl_interface.update_domain(domain);
01307 }
01308 
01309 const String M2MInterfaceImpl::internal_endpoint_name() const
01310 {
01311     return _nsdl_interface.internal_endpoint_name();
01312 }
01313 
01314 const char *M2MInterfaceImpl::error_description() const
01315 {
01316 #ifndef DISABLE_ERROR_DESCRIPTION
01317     return _error_description;
01318 #else
01319     return "";
01320 #endif
01321 }
01322 
01323 void M2MInterfaceImpl::set_error_description(const char *description)
01324 {
01325 #ifndef DISABLE_ERROR_DESCRIPTION
01326     if (strncmp(_error_description, description, sizeof(_error_description)) != 0) {
01327         strncpy(_error_description, description, MAX_ALLOWED_ERROR_STRING_LENGTH - 1);
01328     }
01329 #endif
01330 }
01331 
01332 bool M2MInterfaceImpl::queue_mode() const
01333 {
01334     return (_binding_mode == M2MInterface::UDP_QUEUE ||
01335            _binding_mode == M2MInterface::TCP_QUEUE  ||
01336            _binding_mode == M2MInterface::SMS_QUEUE  ||
01337            _binding_mode == M2MInterface::UDP_SMS_QUEUE);
01338 }
01339 
01340 void M2MInterfaceImpl::get_data_request(DownloadType type,
01341                                         const char *uri,
01342                                         const size_t offset,
01343                                         const bool async,
01344                                         get_data_cb data_cb,
01345                                         get_data_error_cb error_cb,
01346                                         void *context)
01347 {
01348     get_data_req_error_e error = FAILED_TO_SEND_MSG;
01349     if (uri) {
01350         _nsdl_interface.send_request(type, uri, COAP_MSG_CODE_REQUEST_GET, offset, async, 0, 0, NULL, data_cb, error_cb, context);
01351     } else {
01352         error_cb(error, context);
01353     }
01354 }
01355 
01356 void M2MInterfaceImpl::post_data_request(const char *uri,
01357                                          const bool async,
01358                                          const uint16_t payload_len,
01359                                          uint8_t *payload_ptr,
01360                                          get_data_cb data_cb,
01361                                          get_data_error_cb error_cb,
01362                                          void *context)
01363 {
01364     get_data_req_error_e error = FAILED_TO_SEND_MSG;
01365     if (uri) {
01366         _nsdl_interface.send_request(GENERIC_DOWNLOAD, uri, COAP_MSG_CODE_REQUEST_POST, 0, async, 0, payload_len, payload_ptr, data_cb, error_cb, context);
01367     } else {
01368         error_cb(error, context);
01369     }
01370 }
01371 
01372 bool M2MInterfaceImpl::set_uri_query_parameters(const char *uri_query_params)
01373 {
01374     return _nsdl_interface.set_uri_query_parameters(uri_query_params);
01375 }
01376 
01377 void M2MInterfaceImpl::pause()
01378 {
01379     tr_debug("M2MInterfaceImpl::pause");
01380      _connection_handler.claim_mutex();
01381     _queue_sleep_timer.stop_timer();
01382     if (_registration_flow_timer) {
01383         _registration_flow_timer->stop_timer();
01384     }
01385     _connection_handler.unregister_network_handler();
01386     _nsdl_interface.set_request_context_to_be_resend(NULL, 0);
01387     _connection_handler.stop_listening();
01388     _retry_timer.stop_timer();
01389     _reconnecting = false;
01390     _reconnection_time = _initial_reconnection_time;
01391     _reconnection_state = M2MInterfaceImpl::WithUpdate;
01392 
01393     sn_nsdl_clear_coap_resending_queue(_nsdl_interface.get_nsdl_handle());
01394     internal_event(STATE_IDLE);
01395      _connection_handler.release_mutex();
01396 }
01397 
01398 void M2MInterfaceImpl::resume(void *iface, const M2MBaseList &list)
01399 {
01400     tr_debug("M2MInterfaceImpl::resume");
01401     _connection_handler.set_platform_network_handler(iface);
01402     register_object(_security, list);
01403 }