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.
ConnectorClient.cpp
00001 // ---------------------------------------------------------------------------- 00002 // Copyright 2016-2017 ARM Ltd. 00003 // 00004 // SPDX-License-Identifier: Apache-2.0 00005 // 00006 // Licensed under the Apache License, Version 2.0 (the "License"); 00007 // you may not use this file except in compliance with the License. 00008 // You may obtain a copy of the License at 00009 // 00010 // http://www.apache.org/licenses/LICENSE-2.0 00011 // 00012 // Unless required by applicable law or agreed to in writing, software 00013 // distributed under the License is distributed on an "AS IS" BASIS, 00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00015 // See the License for the specific language governing permissions and 00016 // limitations under the License. 00017 // ---------------------------------------------------------------------------- 00018 00019 #include <string> 00020 #include <assert.h> 00021 #include <stdio.h> 00022 #include "include/ConnectorClient.h" 00023 #include "include/CloudClientStorage.h" 00024 #include "include/CertificateParser.h" 00025 #include "MbedCloudClient.h" 00026 #include "mbed-client/m2minterfacefactory.h" 00027 #include "mbed-client/m2mdevice.h" 00028 #include "mbed-trace/mbed_trace.h" 00029 #include "factory_configurator_client.h" 00030 00031 #define TRACE_GROUP "mClt" 00032 00033 #define INTERNAL_ENDPOINT_PARAM "&iep=" 00034 #define DEFAULT_ENDPOINT "endpoint" 00035 #define INTERFACE_ERROR "Client interface is not created. Restart" 00036 #define CREDENTIAL_ERROR "Failed to read credentials from storage" 00037 #define DEVICE_NOT_PROVISIONED "Device not provisioned" 00038 #define ERROR_NO_MEMORY "Not enough memory to stroe LWM2M credentials" 00039 00040 // XXX: nothing here yet 00041 class EventData { 00042 00043 }; 00044 00045 ConnectorClient::ConnectorClient(ConnectorClientCallback* callback) 00046 : _callback(callback), 00047 _current_state(State_Bootstrap_Start), 00048 _event_generated(false), _state_engine_running(false), 00049 _interface(NULL), _security(NULL), 00050 _endpoint_info(M2MSecurity::Certificate), _client_objs(NULL), 00051 _rebootstrap_timer(*this), _bootstrap_security_instance(1), _lwm2m_security_instance(0) 00052 { 00053 assert(_callback != NULL); 00054 00055 // Create the lwm2m server security object we need always 00056 _security = M2MInterfaceFactory::create_security(M2MSecurity::M2MServer); 00057 _interface = M2MInterfaceFactory::create_interface(*this, 00058 DEFAULT_ENDPOINT, // endpoint name string 00059 MBED_CLOUD_CLIENT_ENDPOINT_TYPE, // endpoint type string 00060 MBED_CLOUD_CLIENT_LIFETIME, // lifetime 00061 MBED_CLOUD_CLIENT_LISTEN_PORT, // listen port 00062 _endpoint_info.account_id, // domain string 00063 transport_mode(), // binding mode 00064 M2MInterface::LwIP_IPv4); // network stack 00065 00066 initialize_storage(); 00067 } 00068 00069 00070 ConnectorClient::~ConnectorClient() 00071 { 00072 M2MDevice::delete_instance(); 00073 M2MSecurity::delete_instance(); 00074 delete _interface; 00075 } 00076 00077 void ConnectorClient::start_bootstrap() 00078 { 00079 tr_debug("ConnectorClient::start_bootstrap()"); 00080 assert(_callback != NULL); 00081 // Stop rebootstrap timer if it was running 00082 _rebootstrap_timer.stop_timer(); 00083 if (create_bootstrap_object()) { 00084 _interface->update_endpoint(_endpoint_info.endpoint_name); 00085 _interface->update_domain(_endpoint_info.account_id); 00086 internal_event(State_Bootstrap_Start); 00087 } else { 00088 tr_error("ConnectorClient::start_bootstrap() - bootstrap object fail"); 00089 } 00090 state_engine(); 00091 } 00092 00093 void ConnectorClient::start_registration(M2MObjectList* client_objs) 00094 { 00095 tr_debug("ConnectorClient::start_registration()"); 00096 assert(_callback != NULL); 00097 _client_objs = client_objs; 00098 00099 // XXX: actually this call should be external_event() to match the pattern used in other m2m classes 00100 create_register_object(); 00101 if(_security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { 00102 if(use_bootstrap()) { 00103 // Bootstrap registration always uses iep 00104 _interface->update_endpoint(_endpoint_info.internal_endpoint_name); 00105 } else { 00106 // Registration without bootstrap always uses external id 00107 _interface->update_endpoint(_endpoint_info.endpoint_name); 00108 } 00109 _interface->update_domain(_endpoint_info.account_id); 00110 internal_event(State_Registration_Start); 00111 } else { 00112 tr_error("ConnectorClient::state_init(): failed to create objs"); 00113 _callback->connector_error(M2MInterface::InvalidParameters, INTERFACE_ERROR); 00114 } 00115 state_engine(); 00116 } 00117 00118 M2MInterface * ConnectorClient::m2m_interface() 00119 { 00120 return _interface; 00121 } 00122 00123 void ConnectorClient::update_registration() 00124 { 00125 if(_interface && _security && _security->get_security_instance_id(M2MSecurity::M2MServer) >= 0) { 00126 if (_client_objs != NULL) { 00127 _interface->update_registration(_security, *_client_objs); 00128 } 00129 else { 00130 _interface->update_registration(_security); 00131 } 00132 } 00133 } 00134 00135 // generates an internal event. called from within a state 00136 // function to transition to a new state 00137 void ConnectorClient::internal_event(StartupSubStateRegistration new_state) 00138 { 00139 tr_debug("ConnectorClient::internal_event: state: %d -> %d", _current_state, new_state); 00140 _event_generated = true; 00141 _current_state = new_state; 00142 00143 // Avoid recursive chain which eats too much of stack 00144 if (!_state_engine_running) { 00145 state_engine(); 00146 } 00147 } 00148 00149 // the state engine executes the state machine states 00150 void ConnectorClient::state_engine(void) 00151 { 00152 tr_debug("ConnectorClient::state_engine"); 00153 00154 // this simple flagging gets rid of recursive calls to this method 00155 _state_engine_running = true; 00156 00157 // while events are being generated keep executing states 00158 while (_event_generated) { 00159 _event_generated = false; // event used up, reset flag 00160 00161 state_function(_current_state); 00162 } 00163 00164 _state_engine_running = false; 00165 } 00166 00167 void ConnectorClient::state_function(StartupSubStateRegistration current_state) 00168 { 00169 switch (current_state) { 00170 case State_Bootstrap_Start: 00171 state_bootstrap_start(); 00172 break; 00173 case State_Bootstrap_Started: 00174 state_bootstrap_started(); 00175 break; 00176 case State_Bootstrap_Success: 00177 state_bootstrap_success(); 00178 break; 00179 case State_Bootstrap_Failure: 00180 state_bootstrap_failure(); 00181 break; 00182 case State_Registration_Start: 00183 state_registration_start(); 00184 break; 00185 case State_Registration_Started: 00186 state_registration_started(); 00187 break; 00188 case State_Registration_Success: 00189 state_registration_success(); 00190 break; 00191 case State_Registration_Failure: 00192 state_registration_failure(); 00193 break; 00194 case State_Unregistered: 00195 state_unregistered(); 00196 break; 00197 default: 00198 break; 00199 } 00200 } 00201 00202 /* 00203 * Creates register server object with mbed device server address and other parameters 00204 * required for client to connect to mbed device server. 00205 */ 00206 void ConnectorClient::create_register_object() 00207 { 00208 tr_debug("ConnectorClient::create_register_object()"); 00209 if(_security && _security->get_security_instance_id(M2MSecurity::M2MServer) == -1) { 00210 _security->create_object_instance(M2MSecurity::M2MServer); 00211 int32_t m2m_id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00212 _security->set_resource_value(M2MSecurity::BootstrapServer, M2MSecurity::M2MServer, m2m_id); 00213 // Add ResourceID's and values to the security ObjectID/ObjectInstance 00214 _security->set_resource_value(M2MSecurity::SecurityMode, _endpoint_info.mode, m2m_id); 00215 00216 // Allocate scratch buffer, this will be used to copy parameters from storage to security object 00217 const int max_size = 2048; 00218 uint8_t *buffer = (uint8_t*)malloc(max_size); 00219 size_t real_size = 0; 00220 bool success = false; 00221 if (buffer != NULL) { 00222 success = true; 00223 } 00224 00225 // Connector CA 00226 if (success) { 00227 success = false; 00228 if (get_config_certificate(g_fcc_lwm2m_server_ca_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00229 tr_info("ConnectorClient::create_register_object - ServerPublicKey %d", (int)real_size); 00230 success = true; 00231 _security->set_resource_value(M2MSecurity::ServerPublicKey, 00232 buffer, 00233 (uint32_t)real_size, 00234 m2m_id); 00235 } 00236 else { 00237 tr_error("KEY_CONNECTOR_CA cert failed."); 00238 } 00239 } 00240 00241 // Connector device public key 00242 if (success) { 00243 success = false; 00244 if (get_config_certificate(g_fcc_lwm2m_device_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00245 tr_info("ConnectorClient::create_register_object - PublicKey %d", (int)real_size); 00246 success = true; 00247 _security->set_resource_value(M2MSecurity::PublicKey, buffer, (uint32_t)real_size, m2m_id); 00248 } 00249 else { 00250 tr_error("KEY_CONNECTOR__DEVICE_CERT failed."); 00251 } 00252 } 00253 00254 // Connector device private key 00255 if (success) { 00256 success = false; 00257 if (get_config_private_key(g_fcc_lwm2m_device_private_key_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00258 tr_info("ConnectorClient::create_register_object - SecretKey %d", (int)real_size); 00259 success = true; 00260 _security->set_resource_value(M2MSecurity::Secretkey, buffer, (uint32_t)real_size, m2m_id); 00261 } 00262 else 00263 tr_error("KEY_CONNECTOR_DEVICE_PRIV failed."); 00264 } 00265 00266 // Connector URL 00267 if (success) { 00268 success = false; 00269 if (get_config_parameter(g_fcc_lwm2m_server_uri_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00270 tr_info("ConnectorClient::create_register_object - M2MServerUri %.*s", (int)real_size, buffer); 00271 success = true; 00272 _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, (uint32_t)real_size, m2m_id); 00273 } 00274 else 00275 tr_error("KEY_CONNECTOR_URL failed."); 00276 } 00277 00278 // Endpoint 00279 if (success) { 00280 success = false; 00281 if (get_config_parameter(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00282 tr_info("ConnectorClient::create_register_object - endpoint name %.*s", (int)real_size, buffer); 00283 success = true; 00284 _endpoint_info.endpoint_name = String((const char*)buffer, real_size); 00285 } 00286 else 00287 tr_error("KEY_ENDPOINT_NAME failed."); 00288 } 00289 00290 // Try to get internal endpoint name 00291 if (success) { 00292 if (get_config_parameter(KEY_INTERNAL_ENDPOINT, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00293 _endpoint_info.internal_endpoint_name = String((const char*)buffer, real_size); 00294 tr_info("Using internal endpoint name instead: %s", _endpoint_info.internal_endpoint_name.c_str()); 00295 } 00296 else { 00297 tr_debug("KEY_INTERNAL_ENDPOINT failed."); 00298 } 00299 } 00300 00301 // Account ID, not mandatory 00302 if (success) { 00303 if (get_config_parameter(KEY_ACCOUNT_ID, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00304 tr_info("ConnectorClient::create_register_object - AccountId %.*s", (int)real_size, buffer); 00305 _endpoint_info.account_id = String((const char*)buffer, real_size); 00306 } 00307 else 00308 tr_debug("KEY_ACCOUNT_ID failed."); 00309 } 00310 00311 free(buffer); 00312 if (!success) { 00313 tr_error("ConnectorClient::create_register_object - Failed to read credentials"); 00314 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); 00315 // TODO: what to do with the m2mserver security instance 00316 } 00317 } else { 00318 tr_info("ConnectorClient::create_register_object() - Credentials already exists"); 00319 } 00320 } 00321 00322 /* 00323 * Creates bootstrap server object with bootstrap server address and other parameters 00324 * required for connecting to mbed Cloud bootstrap server. 00325 */ 00326 bool ConnectorClient::create_bootstrap_object() 00327 { 00328 tr_debug("ConnectorClient::create_bootstrap_object"); 00329 bool success = false; 00330 00331 // Check if bootstrap credentials are already stored in KCM 00332 if (bootstrap_credentials_stored_in_kcm() && _security) { 00333 if (_security->get_security_instance_id(M2MSecurity::Bootstrap) == -1) { 00334 _security->create_object_instance(M2MSecurity::Bootstrap); 00335 int32_t bs_id = _security->get_security_instance_id(M2MSecurity::Bootstrap); 00336 _security->set_resource_value(M2MSecurity::SecurityMode, M2MSecurity::Certificate, bs_id); 00337 tr_info("ConnectorClient::create_bootstrap_object - bs_id = %d", bs_id); 00338 tr_info("ConnectorClient::create_bootstrap_object - use credentials from storage"); 00339 00340 // Allocate scratch buffer, this will be used to copy parameters from storage to security object 00341 size_t real_size = 0; 00342 const int max_size = 2048; 00343 uint8_t *buffer = (uint8_t*)malloc(max_size); 00344 if (buffer != NULL) { 00345 success = true; 00346 } 00347 00348 // Read internal endpoint name if it exists, we need to append 00349 // it to bootstrap uri if device already bootstrapped 00350 uint8_t *iep = NULL; 00351 if (success && get_config_parameter_string(KEY_INTERNAL_ENDPOINT, buffer, max_size) == CCS_STATUS_SUCCESS) { 00352 iep = (uint8_t*)malloc(strlen((const char*)buffer) + strlen(INTERNAL_ENDPOINT_PARAM) + 1); 00353 if (iep != NULL) { 00354 strcpy((char*)iep, INTERNAL_ENDPOINT_PARAM); 00355 strcat((char*)iep, (const char*)buffer); 00356 tr_info("ConnectorClient::create_bootstrap_object - iep: %s", buffer); 00357 } 00358 //TODO: Should handle error if iep exists but allocation fails? 00359 } 00360 00361 // Bootstrap URI 00362 if (success) { 00363 success = false; 00364 if (get_config_parameter_string(g_fcc_bootstrap_server_uri_name, buffer, max_size) == CCS_STATUS_SUCCESS) { 00365 success = true; 00366 00367 real_size = strlen((const char*)buffer); 00368 // Append iep if we 1. have it 2. it doesn't already exist in uri 3. it fits 00369 if (iep && 00370 strstr((const char*)buffer, (const char*)iep) == NULL && 00371 (real_size + strlen((const char*)iep) + 1) <= max_size) { 00372 strcat((char*)buffer, (const char*)iep); 00373 real_size += strlen((const char*)iep) + 1; 00374 } 00375 00376 tr_info("ConnectorClient::create_bootstrap_object - M2MServerUri %.*s", (int)real_size, buffer); 00377 _security->set_resource_value(M2MSecurity::M2MServerUri, buffer, real_size, bs_id); 00378 } 00379 } 00380 00381 free(iep); 00382 00383 // Bootstrap server public key (certificate) 00384 if (success) { 00385 success = false; 00386 if (get_config_certificate(g_fcc_bootstrap_server_ca_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00387 success = true; 00388 tr_info("ConnectorClient::create_bootstrap_object - ServerPublicKey %d", (int)real_size); 00389 _security->set_resource_value(M2MSecurity::ServerPublicKey, buffer, real_size, bs_id); 00390 } 00391 } 00392 00393 // Bootstrap client public key (certificate) 00394 if (success) { 00395 success = false; 00396 if (get_config_certificate(g_fcc_bootstrap_device_certificate_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00397 success = true; 00398 tr_info("ConnectorClient::create_bootstrap_object - PublicKey %d", (int)real_size); 00399 _security->set_resource_value(M2MSecurity::PublicKey, buffer, real_size, bs_id); 00400 } 00401 } 00402 00403 // Bootstrap client private key 00404 if (success) { 00405 success = false; 00406 if (get_config_private_key(g_fcc_bootstrap_device_private_key_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00407 success = true; 00408 tr_info("ConnectorClient::create_bootstrap_object - Secretkey %d", (int)real_size); 00409 _security->set_resource_value(M2MSecurity::Secretkey, buffer, real_size, bs_id); 00410 } 00411 } 00412 00413 // Endpoint 00414 if (success) { 00415 success = false; 00416 if (get_config_parameter(g_fcc_endpoint_parameter_name, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00417 success = true; 00418 _endpoint_info.endpoint_name = String((const char*)buffer, real_size); 00419 tr_info("ConnectorClient::create_bootstrap_object - Endpoint %s", _endpoint_info.endpoint_name.c_str()); 00420 } 00421 } 00422 00423 // Account ID, not mandatory 00424 if (success) { 00425 if (get_config_parameter(KEY_ACCOUNT_ID, buffer, max_size, &real_size) == CCS_STATUS_SUCCESS) { 00426 _endpoint_info.account_id = String((const char*)buffer, real_size); 00427 tr_info("ConnectorClient::create_bootstrap_object - AccountId %s", _endpoint_info.account_id.c_str()); 00428 } 00429 } 00430 free(buffer); 00431 00432 if (!success) { 00433 tr_error("ConnectorClient::create_bootstrap_object - Failed to read credentials"); 00434 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorFailedToReadCredentials,CREDENTIAL_ERROR); 00435 _security->remove_object_instance(bs_id); 00436 } 00437 } else { 00438 success = true; 00439 tr_info("ConnectorClient::create_bootstrap_object - bootstrap object already done"); 00440 } 00441 // Device not provisioned 00442 } else { 00443 _callback->connector_error((M2MInterface::Error)MbedCloudClient::ConnectorInvalidCredentials, DEVICE_NOT_PROVISIONED); 00444 tr_error("ConnectorClient::create_bootstrap_object - device not provisioned!"); 00445 } 00446 return success; 00447 } 00448 00449 void ConnectorClient::state_bootstrap_start() 00450 { 00451 tr_info("ConnectorClient::state_bootstrap_start()"); 00452 assert(_interface != NULL); 00453 assert(_security != NULL); 00454 00455 _interface->bootstrap(_security); 00456 00457 internal_event(State_Bootstrap_Started); 00458 } 00459 00460 void ConnectorClient::state_bootstrap_started() 00461 { 00462 // this state may be useful only for verifying the callbacks? 00463 } 00464 00465 void ConnectorClient::state_bootstrap_success() 00466 { 00467 assert(_callback != NULL); 00468 // Parse internal endpoint name from mDS cert 00469 _callback->registration_process_result(State_Bootstrap_Success); 00470 } 00471 00472 void ConnectorClient::state_bootstrap_failure() 00473 { 00474 assert(_callback != NULL); 00475 // maybe some additional canceling and/or leanup is needed here? 00476 _callback->registration_process_result(State_Bootstrap_Failure); 00477 } 00478 00479 void ConnectorClient::state_registration_start() 00480 { 00481 tr_info("ConnectorClient::state_registration_start()"); 00482 assert(_interface != NULL); 00483 assert(_security != NULL); 00484 _interface->register_object(_security, *_client_objs); 00485 internal_event(State_Registration_Started); 00486 } 00487 00488 void ConnectorClient::state_registration_started() 00489 { 00490 // this state may be useful only for verifying the callbacks? 00491 } 00492 00493 void ConnectorClient::state_registration_success() 00494 { 00495 assert(_callback != NULL); 00496 _endpoint_info.internal_endpoint_name = _interface->internal_endpoint_name(); 00497 00498 //The endpoint is maximum 32 character long, we put bigger buffer for future extensions 00499 const int max_size = 64; 00500 uint8_t buffer[max_size]; 00501 00502 bool no_param_update = true; 00503 00504 if(get_config_parameter_string(KEY_INTERNAL_ENDPOINT, buffer, max_size) == CCS_STATUS_SUCCESS) { 00505 if (strcmp((const char*)buffer, _endpoint_info.internal_endpoint_name.c_str()) != 0) { 00506 // Update is required as the stored KCM entry is different than _endpoint_info.internal_endpoint_name. 00507 no_param_update = false; 00508 } 00509 } 00510 00511 // Update INTERNAL_ENDPOINT setting only if there is no such entry or the value is not matching the 00512 // _endpoint_info.internal_endpoint_name. 00513 if(!no_param_update) { 00514 delete_config_parameter(KEY_INTERNAL_ENDPOINT); 00515 set_config_parameter(KEY_INTERNAL_ENDPOINT, (const uint8_t*)_endpoint_info.internal_endpoint_name.c_str(), 00516 (size_t)_endpoint_info.internal_endpoint_name.size()); 00517 } 00518 00519 _callback->registration_process_result(State_Registration_Success); 00520 } 00521 00522 void ConnectorClient::state_registration_failure() 00523 { 00524 assert(_callback != NULL); 00525 // maybe some additional canceling and/or leanup is needed here? 00526 _callback->registration_process_result(State_Registration_Failure); 00527 } 00528 00529 void ConnectorClient::state_unregistered() 00530 { 00531 assert(_callback != NULL); 00532 _callback->registration_process_result(State_Unregistered); 00533 } 00534 00535 void ConnectorClient::bootstrap_done(M2MSecurity *security_object) 00536 { 00537 tr_info("ConnectorClient::bootstrap_done"); 00538 ccs_status_e status = CCS_STATUS_ERROR; 00539 StartupSubStateRegistration state = State_Bootstrap_Success; 00540 if(security_object) { 00541 // Update bootstrap credentials (we could skip this if we knew whether they were updated) 00542 // This will also update the address in case of first to claim 00543 status = set_bootstrap_credentials(security_object); 00544 if (status != CCS_STATUS_SUCCESS) { 00545 // TODO: what now? 00546 tr_error("ConnectorClient::bootstrap_done - couldn't store bootstrap credentials"); 00547 } 00548 00549 // Clear the first to claim flag if it's active 00550 if (is_first_to_claim()) { 00551 status = clear_first_to_claim(); 00552 if (status != CCS_STATUS_SUCCESS) { 00553 // TODO: what now? 00554 tr_error("ConnectorClient::bootstrap_done - couldn't clear first to claim flag!"); 00555 } 00556 } 00557 00558 // Bootstrap might delete m2mserver security object instance completely to force bootstrap 00559 // with new credentials, in that case delete the stored lwm2m credentials as well and re-bootstrap 00560 if (security_object->get_security_instance_id(M2MSecurity::M2MServer) == -1) { 00561 tr_info("ConnectorClient::bootstrap_done() - Clearing lwm2m credentials"); 00562 // delete the old connector credentials when BS sends re-direction. 00563 delete_config_parameter(g_fcc_lwm2m_server_uri_name); 00564 delete_config_certificate(g_fcc_lwm2m_server_ca_certificate_name); 00565 delete_config_certificate(g_fcc_lwm2m_device_certificate_name); 00566 delete_config_private_key(g_fcc_lwm2m_device_private_key_name); 00567 // Start re-bootstrap timer 00568 tr_info("ConnectorClient::bootstrap_done() - Re-directing bootstrap in 100 milliseconds"); 00569 _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true); 00570 return; 00571 } 00572 // Bootstrap wrote M2MServer credentials, store them and also update first to claim status if it's configured 00573 else { 00574 tr_info("ConnectorClient::bootstrap_done() - Storing lwm2m credentials"); 00575 status = set_connector_credentials(security_object); 00576 } 00577 } 00578 if (status != CCS_STATUS_SUCCESS) { 00579 internal_event(State_Bootstrap_Failure); 00580 //Failed to store credentials, bootstrap failed 00581 _callback->connector_error(M2MInterface::MemoryFail, ERROR_NO_MEMORY); // Translated to error code ConnectMemoryConnectFail 00582 return; 00583 } else { 00584 tr_error("ConnectorClient::bootstrap_done - set_credentials status %d", status); 00585 } 00586 internal_event(state); 00587 } 00588 00589 void ConnectorClient::object_registered(M2MSecurity *security_object, const M2MServer &server_object) 00590 { 00591 internal_event(State_Registration_Success); 00592 } 00593 00594 void ConnectorClient::object_unregistered(M2MSecurity *server_object) 00595 { 00596 internal_event(State_Unregistered); 00597 } 00598 00599 void ConnectorClient::registration_updated(M2MSecurity *security_object, const M2MServer & server_object) 00600 { 00601 _callback->registration_process_result(State_Registration_Updated); 00602 } 00603 00604 void ConnectorClient::error(M2MInterface::Error error) 00605 { 00606 tr_error("ConnectorClient::error() - error: %d", error); 00607 assert(_callback != NULL); 00608 if (_current_state >= State_Registration_Start && 00609 use_bootstrap() && 00610 (error == M2MInterface::SecureConnectionFailed || 00611 error == M2MInterface::InvalidParameters)) { 00612 tr_info("ConnectorClient::error() - Error during lwm2m registration"); 00613 tr_info("ConnectorClient::error() - Clearing lwm2m credentials"); 00614 // delete the old connector credentials when DTLS handshake fails or 00615 // server rejects the registration. 00616 delete_config_parameter(g_fcc_lwm2m_server_uri_name); 00617 delete_config_certificate(g_fcc_lwm2m_server_ca_certificate_name); 00618 delete_config_certificate(g_fcc_lwm2m_device_certificate_name); 00619 delete_config_private_key(g_fcc_lwm2m_device_private_key_name); 00620 // Delete the lwm2m security instance 00621 int32_t id = _security->get_security_instance_id(M2MSecurity::M2MServer); 00622 if (id >= 0) { 00623 _security->remove_object_instance(id); 00624 } 00625 // Delete bootstrap security instance 00626 id = _security->get_security_instance_id(M2MSecurity::Bootstrap); 00627 if (id >= 0) { 00628 _security->remove_object_instance(id); 00629 } 00630 // Start re-bootstrap timer 00631 tr_info("ConnectorClient::error() - Re-bootstrapping in 100 milliseconds"); 00632 _rebootstrap_timer.start_timer(100, M2MTimerObserver::BootstrapFlowTimer, true); 00633 } 00634 else { 00635 _callback->connector_error(error, _interface->error_description()); 00636 } 00637 } 00638 00639 void ConnectorClient::value_updated(M2MBase *base, M2MBase::BaseType type) 00640 { 00641 assert(_callback != NULL); 00642 _callback->value_updated(base, type); 00643 } 00644 00645 bool ConnectorClient::connector_credentials_available() 00646 { 00647 tr_debug("ConnectorClient::connector_credentials_available"); 00648 const int max_size = 2048; 00649 uint8_t *buffer = (uint8_t*)malloc(max_size); 00650 size_t real_size = 0; 00651 get_config_private_key(g_fcc_lwm2m_device_private_key_name, buffer, max_size, &real_size); 00652 free(buffer); 00653 if (real_size > 0) { 00654 return true; 00655 } 00656 return false; 00657 } 00658 00659 bool ConnectorClient::use_bootstrap() 00660 { 00661 tr_debug("ConnectorClient::use_bootstrap"); 00662 const int max_size = 32; 00663 uint8_t *buffer = (uint8_t*)malloc(max_size); 00664 bool ret = false; 00665 if (buffer != NULL) { 00666 memset(buffer, 0, max_size); 00667 size_t real_size = 0; 00668 ccs_status_e status = get_config_parameter(g_fcc_use_bootstrap_parameter_name, buffer, max_size, &real_size); 00669 if (status == CCS_STATUS_SUCCESS && real_size > 0 && buffer[0] > 0) { 00670 ret = true; 00671 } 00672 free(buffer); 00673 } 00674 return ret; 00675 } 00676 00677 00678 bool ConnectorClient::get_key(const char *key, const char *endpoint, char *&key_name) 00679 { 00680 if(key_name) { 00681 free(key_name); 00682 key_name = NULL; 00683 } 00684 00685 key_name = (char*)malloc(strlen(key)+strlen(endpoint)+1); 00686 if(key_name) { 00687 strcpy(key_name, key); 00688 strcat(key_name, endpoint); 00689 tr_debug("key %s", key_name); 00690 return true; 00691 } 00692 return false; 00693 } 00694 00695 ccs_status_e ConnectorClient::set_connector_credentials(M2MSecurity *security) 00696 { 00697 tr_debug("ConnectorClient::set_connector_credentials"); 00698 ccs_status_e status = CCS_STATUS_ERROR; 00699 00700 const uint8_t *srv_public_key = NULL; 00701 const uint8_t *public_key = NULL; 00702 const uint8_t *sec_key = NULL; 00703 00704 int32_t m2m_id = security->get_security_instance_id(M2MSecurity::M2MServer); 00705 if (m2m_id == -1) { 00706 return status; 00707 } 00708 00709 uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key, m2m_id); 00710 uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key, m2m_id); 00711 uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key, m2m_id); 00712 00713 if(srv_public_key && public_key && sec_key) { 00714 // Parse common name 00715 char common_name[64]; 00716 memset(common_name, 0, 64); 00717 if (extract_cn_from_certificate(public_key, public_key_size, common_name)){ 00718 tr_info("ConnectorClient::set_connector_credentials - CN: %s", common_name); 00719 _endpoint_info.internal_endpoint_name = String(common_name); 00720 delete_config_parameter(KEY_INTERNAL_ENDPOINT); 00721 status = set_config_parameter(KEY_INTERNAL_ENDPOINT,(uint8_t*)common_name, strlen(common_name)); 00722 } 00723 00724 if(status == CCS_STATUS_SUCCESS) { 00725 delete_config_certificate(g_fcc_lwm2m_server_ca_certificate_name); 00726 status = set_config_certificate(g_fcc_lwm2m_server_ca_certificate_name, 00727 srv_public_key, 00728 (size_t)srv_public_key_size); 00729 } 00730 if(status == CCS_STATUS_SUCCESS) { 00731 status = set_config_certificate(g_fcc_lwm2m_device_certificate_name, 00732 public_key, 00733 (size_t)public_key_size); 00734 } 00735 if(status == CCS_STATUS_SUCCESS) { 00736 status = set_config_private_key(g_fcc_lwm2m_device_private_key_name, 00737 sec_key, 00738 (size_t)sec_key_size); 00739 } 00740 00741 if(status == CCS_STATUS_SUCCESS) { 00742 delete_config_parameter(KEY_ACCOUNT_ID); 00743 // AccountID optional so don't fail if unable to store 00744 set_config_parameter(KEY_ACCOUNT_ID, 00745 (const uint8_t*)_endpoint_info.account_id.c_str(), 00746 (size_t)_endpoint_info.account_id.size()); 00747 } 00748 if(status == CCS_STATUS_SUCCESS) { 00749 status = set_config_parameter(g_fcc_lwm2m_server_uri_name, 00750 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).c_str(), 00751 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, m2m_id).size()); 00752 } 00753 M2MDevice *device = M2MInterfaceFactory::create_device(); 00754 if (device) { 00755 String temp = ""; 00756 uint32_t currenttime = (uint32_t)device->resource_value_int(M2MDevice::CurrentTime, 0); 00757 uint8_t data[4]; 00758 memcpy(data, ¤ttime, 4); 00759 delete_config_parameter(g_fcc_current_time_parameter_name); 00760 set_config_parameter(g_fcc_current_time_parameter_name, data, 4); 00761 00762 temp = device->resource_value_string(M2MDevice::Timezone, 0); 00763 delete_config_parameter(g_fcc_device_time_zone_parameter_name); 00764 set_config_parameter(g_fcc_device_time_zone_parameter_name, (const uint8_t*)temp.c_str(), temp.size()); 00765 00766 temp = device->resource_value_string(M2MDevice::UTCOffset, 0); 00767 delete_config_parameter(g_fcc_offset_from_utc_parameter_name); 00768 set_config_parameter(g_fcc_offset_from_utc_parameter_name, (const uint8_t*)temp.c_str(), temp.size()); 00769 00770 status = CCS_STATUS_SUCCESS; 00771 } 00772 else { 00773 tr_debug("No device object to store!"); 00774 } 00775 } 00776 00777 return status; 00778 } 00779 00780 ccs_status_e ConnectorClient::set_bootstrap_credentials(M2MSecurity *security) 00781 { 00782 tr_debug("ConnectorClient::set_bootstrap_credentials"); 00783 ccs_status_e status = CCS_STATUS_ERROR; 00784 00785 const uint8_t *srv_public_key = NULL; 00786 const uint8_t *public_key = NULL; 00787 const uint8_t *sec_key = NULL; 00788 00789 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); 00790 if (bs_id == -1) { 00791 return status; 00792 } 00793 00794 uint32_t srv_public_key_size = security->resource_value_buffer(M2MSecurity::ServerPublicKey, srv_public_key, bs_id); 00795 uint32_t public_key_size = security->resource_value_buffer(M2MSecurity::PublicKey, public_key, bs_id); 00796 uint32_t sec_key_size = security->resource_value_buffer(M2MSecurity::Secretkey, sec_key, bs_id); 00797 00798 if(srv_public_key && public_key && sec_key) { 00799 delete_config_certificate(g_fcc_bootstrap_server_ca_certificate_name); 00800 status = set_config_certificate(g_fcc_bootstrap_server_ca_certificate_name, 00801 srv_public_key, 00802 (size_t)srv_public_key_size); 00803 if(status == CCS_STATUS_SUCCESS) { 00804 delete_config_certificate(g_fcc_bootstrap_device_certificate_name); 00805 status = set_config_certificate(g_fcc_bootstrap_device_certificate_name, 00806 public_key, 00807 (size_t)public_key_size); 00808 } 00809 if(status == CCS_STATUS_SUCCESS) { 00810 delete_config_private_key(g_fcc_bootstrap_device_private_key_name); 00811 status = set_config_private_key(g_fcc_bootstrap_device_private_key_name, 00812 sec_key, 00813 (size_t)sec_key_size); 00814 } 00815 if(status == CCS_STATUS_SUCCESS) { 00816 delete_config_parameter(g_fcc_bootstrap_server_uri_name); 00817 status = set_config_parameter(g_fcc_bootstrap_server_uri_name, 00818 (const uint8_t*)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).c_str(), 00819 (size_t)security->resource_value_string(M2MSecurity::M2MServerUri, bs_id).size()); 00820 } 00821 } 00822 00823 return status; 00824 } 00825 00826 ccs_status_e ConnectorClient::store_bootstrap_address(M2MSecurity *security) 00827 { 00828 tr_debug("ConnectorClient::store_bootstrap_address"); 00829 ccs_status_e status = CCS_STATUS_ERROR; 00830 00831 const uint8_t *srv_address = NULL; 00832 int32_t bs_id = security->get_security_instance_id(M2MSecurity::Bootstrap); 00833 if (bs_id == -1) { 00834 return status; 00835 } 00836 00837 uint32_t srv_address_size = security->resource_value_buffer(M2MSecurity::M2MServerUri, srv_address, bs_id); 00838 00839 if(srv_address) { 00840 delete_config_parameter(g_fcc_bootstrap_server_uri_name); 00841 status = set_config_parameter(g_fcc_bootstrap_server_uri_name, 00842 srv_address, 00843 (size_t)srv_address_size); 00844 } 00845 00846 return status; 00847 } 00848 00849 ccs_status_e ConnectorClient::clear_first_to_claim() 00850 { 00851 tr_debug("ConnectorClient::clear_first_to_claim"); 00852 return delete_config_parameter(KEY_FIRST_TO_CLAIM); 00853 } 00854 00855 00856 const ConnectorClientEndpointInfo *ConnectorClient::endpoint_info() const 00857 { 00858 return &_endpoint_info; 00859 } 00860 00861 bool ConnectorClient::bootstrap_credentials_stored_in_kcm() 00862 { 00863 size_t real_size = 0; 00864 ccs_status_e success = size_config_parameter(g_fcc_bootstrap_server_uri_name, &real_size); 00865 // Return true if bootstrap uri exists in KCM 00866 if ((success == CCS_STATUS_SUCCESS) && real_size > 0) { 00867 return true; 00868 } else { 00869 return false; 00870 } 00871 } 00872 00873 bool ConnectorClient::is_first_to_claim() 00874 { 00875 size_t real_size = 0; 00876 uint8_t data[4] = {0}; 00877 uint32_t value = 0; 00878 ccs_status_e status = get_config_parameter(KEY_FIRST_TO_CLAIM, data, 4, &real_size); 00879 if (status == CCS_STATUS_SUCCESS) { 00880 memcpy(&value, data, 4); 00881 // Return true if bootstrap uri exists in KCM 00882 if (value == 1) { 00883 return true; 00884 } 00885 } 00886 return false; 00887 } 00888 00889 void ConnectorClient::timer_expired(M2MTimerObserver::Type type) 00890 { 00891 if (type == M2MTimerObserver::BootstrapFlowTimer) { 00892 start_bootstrap(); 00893 } 00894 } 00895 00896 M2MInterface::BindingMode ConnectorClient::transport_mode() 00897 { 00898 #ifdef MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP 00899 return M2MInterface::UDP; 00900 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP 00901 return M2MInterface::TCP; 00902 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_UDP_QUEUE 00903 return M2MInterface::UDP_QUEUE; 00904 #elif defined MBED_CLOUD_CLIENT_TRANSPORT_MODE_TCP_QUEUE 00905 return M2MInterface::TCP_QUEUE; 00906 #else 00907 return M2MInterface::UDP; 00908 #endif 00909 }
Generated on Tue Jul 12 2022 19:01:34 by
1.7.2