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