Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Mon Aug 29 2022 19:53:39 by
