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