Simple interface for Mbed Cloud Client

Dependents:  

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers m2minterfaceimpl.cpp Source File

m2minterfaceimpl.cpp

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