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.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
thread_management_client.c
00001 /* 00002 * Copyright (c) 2014-2018, Arm Limited and affiliates. 00003 * SPDX-License-Identifier: BSD-3-Clause 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions are met: 00007 * 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the copyright holder nor the 00014 * names of its contributors may be used to endorse or promote products 00015 * derived from this software without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00018 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 00021 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00022 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00023 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00024 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00025 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00026 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00027 * POSSIBILITY OF SUCH DAMAGE. 00028 */ 00029 00030 00031 #include "nsconfig.h" 00032 #ifdef HAVE_THREAD 00033 #include <ns_types.h> 00034 #include "ns_list.h" 00035 #include "ns_trace.h" 00036 #include "nsdynmemLIB.h" 00037 #include "common_functions.h" 00038 #include "thread_tmfcop_lib.h" 00039 00040 #include "coap_service_api.h" 00041 00042 #include "thread_common.h" 00043 #include "thread_config.h" 00044 #include "thread_management_if.h" 00045 #include "6LoWPAN/Thread/thread_constants.h" 00046 #include "6LoWPAN/Thread/thread_tmfcop_lib.h" 00047 #include "6LoWPAN/Thread/thread_management_internal.h" 00048 #include "6LoWPAN/Thread/thread_management_server.h" 00049 #include "6LoWPAN/Thread/thread_joiner_application.h" 00050 #include "6LoWPAN/Thread/thread_network_data_lib.h" 00051 #include "6LoWPAN/Thread/thread_bootstrap.h" 00052 #include "6LoWPAN/Thread/thread_management_client.h" 00053 #include "NWK_INTERFACE/Include/protocol.h" 00054 00055 #define TRACE_GROUP TRACE_GROUP_THREAD_MANAGEMENT_CLIENT 00056 00057 typedef struct thread_management { 00058 thread_management_client_router_id_cb *router_id_cb_ptr; 00059 thread_management_client_router_id_cb *router_id_release_cb_ptr; 00060 thread_management_client_network_data_set_cb *network_data_set_cb_ptr; 00061 thread_management_client_network_data_set_cb *neighbor_discovery_cb_ptr; 00062 int8_t interface_id; 00063 int8_t coap_service_id; // COAP service ID from Management server 00064 ns_list_link_t link; 00065 } thread_management_t; 00066 00067 static NS_LIST_DEFINE(instance_list, thread_management_t, link); 00068 00069 static thread_management_t *thread_management_find(int8_t interface_id) 00070 { 00071 thread_management_t *this = NULL; 00072 ns_list_foreach(thread_management_t, cur_ptr, &instance_list) { 00073 if (cur_ptr->interface_id == interface_id) { 00074 this = cur_ptr; 00075 break; 00076 } 00077 } 00078 return this; 00079 } 00080 static thread_management_t *thread_management_find_by_service(int8_t service_id) 00081 { 00082 thread_management_t *this = NULL; 00083 ns_list_foreach(thread_management_t, cur_ptr, &instance_list) { 00084 if (cur_ptr->coap_service_id == service_id) { 00085 this = cur_ptr; 00086 break; 00087 } 00088 } 00089 return this; 00090 } 00091 00092 static int thread_management_client_get_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00093 { 00094 thread_management_t *this = thread_management_find_by_service(service_id); 00095 uint8_t *router_id_mask_ptr; 00096 uint16_t router_id; 00097 uint8_t *ptr; 00098 int8_t status = 0; 00099 (void)source_address; 00100 (void)source_port; 00101 00102 tr_debug("Thread router id client cb"); 00103 if (!this) { 00104 return -1; 00105 } 00106 00107 if ((!response_ptr) || 9 > thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_ROUTER_MASK, &router_id_mask_ptr) || 00108 2 > thread_meshcop_tlv_data_get_uint16(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_RLOC16, &router_id) || 00109 1 > thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_STATUS, &ptr) || *ptr != 0) { 00110 // Failure in message 00111 status = -1; 00112 router_id_mask_ptr = NULL; 00113 router_id = 0xfffe; 00114 } 00115 00116 if (this->router_id_cb_ptr) { 00117 this->router_id_cb_ptr(this->interface_id, status, router_id, router_id_mask_ptr); 00118 } 00119 00120 return 0; 00121 } 00122 00123 static int thread_management_client_release_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00124 { 00125 thread_management_t *this = thread_management_find_by_service(service_id); 00126 (void) source_address; 00127 (void) source_port; 00128 (void) response_ptr; 00129 if (this && this->router_id_release_cb_ptr) { 00130 this->router_id_release_cb_ptr(this->interface_id, 0, 0xfffe, NULL); 00131 } 00132 return 0; 00133 } 00134 00135 /** 00136 * Public Api functions 00137 */ 00138 void thread_management_client_init(int8_t interface_id) 00139 { 00140 thread_management_t *this = thread_management_find(interface_id); 00141 if (this) { 00142 return; 00143 } 00144 00145 this = ns_dyn_mem_alloc(sizeof(thread_management_t)); 00146 00147 if (this) { 00148 this->network_data_set_cb_ptr = NULL; 00149 this->router_id_release_cb_ptr = NULL; 00150 this->neighbor_discovery_cb_ptr = NULL; 00151 this->router_id_cb_ptr = NULL; 00152 this->interface_id = interface_id; 00153 //TODO: Check if to use ephemeral port here 00154 00155 this->coap_service_id = thread_management_server_service_id_get(interface_id); 00156 if (this->coap_service_id < 0) { 00157 tr_error("Failed to init COAP service"); 00158 } 00159 ns_list_add_to_start(&instance_list, this); 00160 } 00161 return; 00162 } 00163 00164 void thread_management_client_delete(int8_t interface_id) 00165 { 00166 thread_management_t *this = thread_management_find(interface_id); 00167 if (!this) { 00168 return; 00169 } 00170 00171 ns_list_remove(&instance_list, this); 00172 ns_dyn_mem_free(this); 00173 return; 00174 } 00175 00176 int thread_management_client_router_id_get(int8_t interface_id, uint8_t mac[8], uint16_t router_id, thread_management_client_router_id_cb *id_cb, uint8_t status) 00177 { 00178 thread_management_t *this = thread_management_find(interface_id); 00179 uint8_t payload[30];//!< max length 4 + 2, 4 + 8, 4 + 8, 00180 uint8_t destination[16]; 00181 uint8_t *ptr; 00182 protocol_interface_info_entry_t *cur; 00183 00184 if (!this || !mac || !id_cb) { 00185 return -1; 00186 } 00187 00188 if (0 != thread_management_get_leader_address(interface_id, destination)) { 00189 return -2; 00190 } 00191 00192 cur = protocol_stack_interface_info_get_by_id(interface_id); 00193 if (!cur || !cur->thread_info) { 00194 return -3; 00195 } 00196 00197 this->router_id_cb_ptr = id_cb; 00198 ptr = payload; 00199 if (router_id < 0xfffe) { 00200 ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, router_id); 00201 } 00202 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_MAC_ADDRESS, 8, mac); 00203 00204 tr_debug("thread router id get id: %d, mac %s", router_id, trace_array(mac, 8)); 00205 00206 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, TMFCOP_TLV_STATUS, status); 00207 00208 return coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, 00209 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ROUTER_ID_ASSIGNMENT, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_get_cb); 00210 } 00211 00212 int thread_management_client_router_id_release(int8_t interface_id, uint8_t mac[8], uint16_t router_id, thread_management_client_router_id_cb *id_cb) 00213 { 00214 thread_management_t *this = thread_management_find(interface_id); 00215 uint8_t payload[30];//!< max length 4 + 2, 4 + 8, 4 + 8, 00216 uint8_t destination[16]; 00217 uint8_t *ptr; 00218 00219 if (!this || !mac || router_id >= 0xfffe) { 00220 return -1; 00221 } 00222 00223 if (0 != thread_management_get_leader_address(interface_id, destination)) { 00224 return -2; 00225 } 00226 00227 this->router_id_release_cb_ptr = id_cb; 00228 ptr = payload; 00229 ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, router_id); 00230 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_MAC_ADDRESS, 8, mac); 00231 00232 tr_debug("thread router id release id: %d, mac %s", router_id, trace_array(mac, 8)); 00233 00234 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, 00235 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ROUTER_ID_RELEASE, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_release_cb); 00236 return 0; 00237 } 00238 00239 static int thread_management_client_register_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00240 { 00241 thread_management_t *this = thread_management_find_by_service(service_id); 00242 (void) source_address; 00243 (void) source_port; 00244 if (!this) { 00245 return -1; 00246 } 00247 00248 if (this->network_data_set_cb_ptr) { 00249 if (response_ptr) { 00250 // If we get response status is OK 00251 this->network_data_set_cb_ptr(this->interface_id, 0, response_ptr->payload_ptr, response_ptr->payload_len); 00252 } else { 00253 this->network_data_set_cb_ptr(this->interface_id, -1, NULL, 0); 00254 } 00255 } 00256 00257 return 0; 00258 } 00259 00260 int thread_management_client_network_data_register(int8_t interface_id, uint8_t *data_ptr, uint16_t data_len, thread_management_client_network_data_set_cb *set_cb) 00261 { 00262 thread_management_t *this = thread_management_find(interface_id); 00263 uint8_t destination[16]; 00264 00265 if (!this) { 00266 return -1; 00267 } 00268 00269 if (thread_management_get_leader_address(interface_id, destination)) { 00270 return -2; 00271 } 00272 00273 this->network_data_set_cb_ptr = set_cb; 00274 tr_debug("thread network data send to %s", trace_ipv6(destination)); 00275 00276 return coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, 00277 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, data_ptr, data_len, thread_management_client_register_cb); 00278 } 00279 00280 int thread_management_client_network_data_unregister(int8_t interface_id, uint16_t rloc16) 00281 { 00282 thread_management_t *this = thread_management_find(interface_id); 00283 uint8_t payload[4]; 00284 uint8_t *ptr; 00285 uint8_t destination[16]; 00286 00287 if (!this) { 00288 return -1; 00289 } 00290 00291 if (thread_management_get_leader_address(interface_id, destination)) { 00292 return -2; 00293 } 00294 ptr = payload; 00295 ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, rloc16); 00296 00297 tr_debug("thread network data unregister"); 00298 00299 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, 00300 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NETWORK_DATA, COAP_CT_OCTET_STREAM, payload, ptr - payload, thread_management_client_register_cb); 00301 return 0; 00302 } 00303 00304 static int thread_management_client_neighbor_discovery_data_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00305 { 00306 thread_management_t *this = thread_management_find_by_service(service_id); 00307 uint8_t *nd_data_options_ptr = NULL; 00308 int8_t status = -1; 00309 uint16_t nd_data_options_len = 0; 00310 (void) source_address; 00311 (void) source_port; 00312 if (!this) { 00313 return -1; 00314 } 00315 00316 if (response_ptr) { 00317 status = 0; // If we get response status is OK 00318 nd_data_options_len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_ND_DATA, &nd_data_options_ptr); 00319 } 00320 00321 if (this->neighbor_discovery_cb_ptr) { 00322 this->neighbor_discovery_cb_ptr(this->interface_id, status, nd_data_options_ptr, nd_data_options_len); 00323 } 00324 00325 return 0; 00326 } 00327 00328 int thread_management_client_get_interface_id_by_service_id(int8_t service_id) 00329 { 00330 thread_management_t *this = thread_management_find_by_service(service_id); 00331 if (!this) { 00332 return -1; 00333 } 00334 return this->interface_id; 00335 } 00336 00337 int thread_management_client_neighbor_discovery_data_request(int8_t interface_id, const uint8_t destination[16], const uint8_t *options, uint8_t options_len, thread_management_client_network_data_set_cb *set_cb) 00338 { 00339 thread_management_t *this = thread_management_find(interface_id); 00340 uint8_t payload[2 + options_len]; //type + length + num of options 00341 uint8_t *ptr = &payload[2]; 00342 uint8_t payload_len; 00343 00344 if (!this || !options || options_len == 0) { 00345 return -1; 00346 } 00347 00348 this->neighbor_discovery_cb_ptr = set_cb; 00349 tr_debug("thread neighbor discovery data request"); 00350 00351 memcpy(ptr, options, options_len); 00352 thread_tmfcop_tlv_data_write_header(payload, TMFCOP_TLV_ND_OPTION, options_len); 00353 payload_len = 2 + options_len; //type + length + options 00354 00355 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT, 00356 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_NEIGHBOR_DISCOVERY_DATA_REQ, COAP_CT_OCTET_STREAM, payload, payload_len, thread_management_client_neighbor_discovery_data_cb); 00357 return 0; 00358 } 00359 00360 static int thread_management_client_active_set_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00361 { 00362 thread_management_t *this = thread_management_find_by_service(service_id); 00363 (void)source_address; 00364 (void)source_port; 00365 uint8_t state; 00366 00367 tr_debug("Receiving active set response from leader"); 00368 00369 if (!this) { 00370 return -1; 00371 } 00372 00373 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00374 00375 if (!cur || !cur->thread_info) { 00376 return -2; 00377 } 00378 00379 if (!response_ptr || response_ptr->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED || !response_ptr->payload_ptr) { 00380 tr_error("active set failed"); 00381 goto getout; 00382 } 00383 if (1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &state) || state != 1) { 00384 tr_error("active set rejected"); 00385 goto getout; 00386 } 00387 // TODO this is problematic we can not advertise before leader distributes the data 00388 // Current approach is to wait for leader 00389 // Spec says we could form own partition or just learn the older ones 00390 // We could then just clear timestamp from active set and learn new one. 00391 // thread_active_configuration_dataset_query_done(cur); 00392 return 0; 00393 00394 getout: 00395 00396 return 0; 00397 } 00398 00399 int8_t thread_management_client_active_set(int8_t interface_id, uint8_t *dst_address) 00400 { 00401 thread_management_t *this = thread_management_find(interface_id); 00402 uint16_t response_len; 00403 uint8_t *response_ptr, *ptr; 00404 tr_debug("Sending active set to leader"); 00405 00406 response_len = thread_joiner_application_next_active_config_length(interface_id); 00407 if (!this || response_len < 1) { 00408 return -1; 00409 } 00410 00411 response_ptr = ns_dyn_mem_alloc(response_len); 00412 if (!response_ptr) { 00413 tr_warn("Out of mem"); 00414 return -2; 00415 } 00416 ptr = thread_joiner_application_next_active_config_write(interface_id, response_ptr); 00417 00418 if (0 == coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, dst_address, THREAD_MANAGEMENT_PORT, 00419 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_ACTIVE_SET, COAP_CT_OCTET_STREAM, response_ptr, (uint16_t)(ptr - response_ptr), thread_management_client_active_set_response_cb)) { 00420 tr_warn("request send failed"); 00421 } 00422 ns_dyn_mem_free(response_ptr); 00423 return 0; 00424 } 00425 00426 00427 static int thread_management_client_pending_set_response_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00428 { 00429 thread_management_t *this = thread_management_find_by_service(service_id); 00430 (void)source_address; 00431 (void)source_port; 00432 uint8_t state; 00433 00434 tr_debug("Receiving pending set response from leader"); 00435 00436 if (!this) { 00437 return -1; 00438 } 00439 00440 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00441 00442 if (!cur || !cur->thread_info) { 00443 return -2; 00444 } 00445 00446 if (!response_ptr || response_ptr->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED || !response_ptr->payload_ptr) { 00447 tr_error("pending set failed"); 00448 goto getout; 00449 } 00450 if (1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &state) || state != 1) { 00451 tr_error("pending set rejected"); 00452 goto getout; 00453 } 00454 00455 return 0; 00456 00457 getout: 00458 return 0; 00459 } 00460 00461 int8_t thread_management_client_pending_set(int8_t interface_id, uint8_t *dst_address) 00462 { 00463 thread_management_t *this = thread_management_find(interface_id); 00464 uint16_t response_len; 00465 uint8_t *response_ptr, *ptr; 00466 tr_debug("Sending Pending set to leader"); 00467 00468 if (!this) { 00469 return -1; 00470 } 00471 00472 response_len = thread_joiner_application_next_pending_config_length(interface_id); 00473 00474 response_ptr = ns_dyn_mem_alloc(response_len); 00475 if (!response_ptr) { 00476 tr_warn("Out of mem"); 00477 return -2; 00478 } 00479 ptr = thread_joiner_application_next_pending_config_build(interface_id, response_ptr); 00480 00481 if (0 == coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, dst_address, THREAD_MANAGEMENT_PORT, 00482 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_PENDING_SET, COAP_CT_OCTET_STREAM, response_ptr, (uint16_t)(ptr - response_ptr), thread_management_client_pending_set_response_cb)) { 00483 tr_warn("request send failed"); 00484 } 00485 ns_dyn_mem_free(response_ptr); 00486 return 0; 00487 } 00488 00489 static int thread_management_client_provision_request_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00490 { 00491 thread_management_t *this = thread_management_find_by_service(service_id); 00492 (void)source_address; 00493 (void)source_port; 00494 uint8_t state; 00495 00496 tr_debug("Thread provisioning Received"); 00497 00498 if (!this) { 00499 return 0; 00500 } 00501 00502 thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_NOT_DONE); 00503 00504 // CoAP request timed out 00505 if (!response_ptr) { 00506 return 0; 00507 } 00508 00509 if (response_ptr->msg_code != COAP_MSG_CODE_RESPONSE_CHANGED) { 00510 tr_error("Provisioning failed"); 00511 thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_REJECTED); 00512 return 0; 00513 } 00514 00515 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id); 00516 00517 if (!cur || !cur->thread_info || 1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &state)) { 00518 tr_error("provisioning response failed"); 00519 return 0; 00520 } 00521 tr_debug("Thread provisioning status %d", state); 00522 00523 if (state == 1) { 00524 thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_DONE); 00525 } else { 00526 thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_REJECTED); 00527 } 00528 00529 return 0; 00530 } 00531 00532 int thread_management_client_provision_request(int8_t interface_id, uint8_t *dst_address, uint16_t port) 00533 { 00534 thread_management_t *this; 00535 uint8_t *ptr, *data_ptr; 00536 uint16_t length; 00537 00538 if (thread_joiner_application_provisioning_get(interface_id) == PROVISIONING_STATUS_ONGOING) { 00539 // wait for response to to the message 00540 return 0; 00541 } 00542 00543 tr_debug("Thread provisioning start send"); 00544 this = thread_management_find(interface_id); 00545 device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(interface_id); 00546 00547 if (!this || !device_configuration_ptr) { 00548 return -1; 00549 } 00550 length = thread_joiner_application_device_configuration_length(device_configuration_ptr); 00551 length += 3;// State 00552 00553 data_ptr = ptr = ns_dyn_mem_alloc(length); 00554 if (!ptr) { 00555 tr_error("Failed to start Commissioning"); 00556 return -1; 00557 } 00558 ptr = thread_joiner_application_device_configuration_build(ptr, device_configuration_ptr); 00559 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 1); 00560 00561 00562 thread_joiner_application_provisioning_set(interface_id, PROVISIONING_STATUS_ONGOING); 00563 00564 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, dst_address, port, 00565 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_CT_OCTET_STREAM, 00566 data_ptr, ptr - data_ptr, thread_management_client_provision_request_cb); 00567 00568 ns_dyn_mem_free(data_ptr); 00569 00570 return 0; 00571 } 00572 00573 static int thread_management_client_proactive_an_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00574 { 00575 (void) service_id; 00576 (void) source_address; 00577 (void) source_port; 00578 (void) response_ptr; 00579 return 0; 00580 } 00581 00582 void thread_management_client_proactive_an(int8_t interface_id, const uint8_t address[16], const uint16_t rloc, const uint8_t ml_eid[8], const uint8_t dst_addr[16]) 00583 { 00584 thread_management_t *this = thread_management_find(interface_id); 00585 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00586 00587 if (!this || !cur) { 00588 tr_warn("No resolution client or protocol info!"); 00589 return; 00590 } 00591 00592 tr_debug("Thread resolution client; proactive address notification"); 00593 00594 uint8_t payload[2 + 16 + 2 + 2 + 2 + 8]; 00595 uint8_t *ptr; 00596 00597 ptr = payload; 00598 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_TARGET_EID, 16, address); 00599 ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, rloc); 00600 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_ML_EID, 8, ml_eid); 00601 00602 coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, 00603 dst_addr, THREAD_MANAGEMENT_PORT, 00604 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, 00605 THREAD_URI_ADDRESS_NOTIFICATION, COAP_CT_OCTET_STREAM, 00606 payload, ptr - payload, thread_management_client_proactive_an_cb); 00607 } 00608 void thread_management_client_coap_message_delete(int8_t interface_id, uint16_t coap_message_id) 00609 { 00610 thread_management_t *this = thread_management_find(interface_id); 00611 00612 if (!this) { 00613 return; 00614 } 00615 00616 coap_service_request_delete(this->coap_service_id, coap_message_id); 00617 } 00618 00619 void thread_management_client_old_partition_data_clean(int8_t interface_id) 00620 { 00621 thread_management_t *this = thread_management_find(interface_id); 00622 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00623 00624 if (!this || !cur) { 00625 return; 00626 } 00627 00628 cur->thread_info->localServerDataBase.publish_coap_req_id = 0; 00629 cur->thread_info->routerIdRequested = false; 00630 coap_service_request_delete_by_service_id(this->coap_service_id); 00631 } 00632 00633 #ifdef HAVE_THREAD_V2 00634 void thread_management_client_addr_ntf_send(int8_t interface_id, uint8_t *destination_address, const uint8_t *addr_data_ptr, uint8_t bbr_status) 00635 { 00636 uint8_t payload[16 + 1]; // Target eid + Status 00637 uint8_t *ptr; 00638 uint8_t br_ml_addr[16]; 00639 uint8_t seq; 00640 uint32_t delay_timer; 00641 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00642 00643 if (!cur) { 00644 return; 00645 } 00646 00647 if (!thread_bootstrap_is_domain_prefix(cur, addr_data_ptr)) { 00648 return; 00649 } 00650 00651 if (0 != thread_common_primary_bbr_get(cur, br_ml_addr, &seq, &delay_timer, NULL)) { 00652 // No pBBR present 00653 return; 00654 } 00655 00656 ptr = payload; 00657 ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_TARGET_EID, 16, addr_data_ptr); 00658 ptr = thread_tmfcop_tlv_data_write_uint8(ptr, TMFCOP_TLV_STATUS, bbr_status); 00659 00660 coap_service_request_send(thread_management_server_service_id_get(cur->id), COAP_REQUEST_OPTIONS_ADDRESS_SHORT, 00661 destination_address, THREAD_MANAGEMENT_PORT, 00662 COAP_MSG_TYPE_NON_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, 00663 THREAD_URI_BBR_DOMAIN_ADDRESS_NOTIFICATION, COAP_CT_OCTET_STREAM, 00664 payload, ptr - payload, NULL); 00665 return; 00666 } 00667 static int thread_bootstrap_mlr_cb(int8_t service_id, uint8_t source_address[static 16], uint16_t source_port, sn_coap_hdr_s *response_ptr) 00668 { 00669 (void) service_id; 00670 (void) source_address; 00671 (void) source_port; 00672 (void) response_ptr; 00673 00674 tr_debug("Thread MLR callback"); 00675 return 0; 00676 } 00677 00678 int thread_management_client_mlr_req_send(int8_t interface_id, const uint8_t br_addr[16], const uint8_t *address, uint8_t address_len) 00679 { 00680 protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id); 00681 00682 if (!cur || !br_addr || !address) { 00683 return -1; 00684 } 00685 tr_debug("thread MLR.req send"); 00686 00687 coap_service_request_send(thread_management_server_service_id_get(cur->id), COAP_REQUEST_OPTIONS_NONE, br_addr, THREAD_MANAGEMENT_PORT, 00688 COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_BBR_MCAST_LISTENER_REPORT, COAP_CT_OCTET_STREAM, address, address_len, thread_bootstrap_mlr_cb); 00689 return 0; 00690 } 00691 #endif 00692 #endif
Generated on Tue Jul 12 2022 13:54:59 by
1.7.2