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.
Dependencies: FXAS21002 FXOS8700Q
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 Tue Jul 12 2022 20:21:00 by
