takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers thread_management_client.c Source File

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_joiner_application.h"
00049 #include "6LoWPAN/Thread/thread_network_data_lib.h"
00050 #include "6LoWPAN/Thread/thread_bootstrap.h"
00051 #include "6LoWPAN/Thread/thread_management_client.h"
00052 #include "NWK_INTERFACE/Include/protocol.h"
00053 
00054 #define TRACE_GROUP TRACE_GROUP_THREAD_MANAGEMENT_CLIENT
00055 
00056 typedef struct thread_management {
00057     thread_management_client_router_id_cb *router_id_cb_ptr;
00058     thread_management_client_router_id_cb *router_id_release_cb_ptr;
00059     thread_management_client_network_data_set_cb *network_data_set_cb_ptr;
00060     thread_management_client_network_data_set_cb *neighbor_discovery_cb_ptr;
00061     uint16_t coap_asd_msg_id;   // COAP msg id for a/sd
00062     int8_t interface_id;
00063     int8_t coap_service_id;
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         this->coap_asd_msg_id = 0;
00154         //TODO: Check if to use ephemeral port here
00155         this->coap_service_id = coap_service_initialize(this->interface_id, THREAD_MANAGEMENT_PORT, COAP_SERVICE_OPTIONS_NONE, NULL, NULL);
00156         ns_list_add_to_start(&instance_list, this);
00157     }
00158     return;
00159 }
00160 
00161 void thread_management_client_delete(int8_t interface_id)
00162 {
00163     thread_management_t *this = thread_management_find(interface_id);
00164     if (!this) {
00165         return;
00166     }
00167 
00168     coap_service_delete(this->coap_service_id);
00169     ns_list_remove(&instance_list, this);
00170     ns_dyn_mem_free(this);
00171     return;
00172 }
00173 int8_t thread_management_client_service_id_get(int8_t interface_id)
00174 {
00175     thread_management_t *this = thread_management_find(interface_id);
00176     if (!this) {
00177         return -1;
00178     }
00179     return this->coap_service_id;
00180 }
00181 
00182 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)
00183 {
00184     thread_management_t *this = thread_management_find(interface_id);
00185     uint8_t payload[30];//!< max length 4 + 2, 4 + 8,  4 + 8,
00186     uint8_t destination[16];
00187     uint8_t *ptr;
00188     protocol_interface_info_entry_t *cur;
00189 
00190     if (!this || !mac || !id_cb) {
00191         return -1;
00192     }
00193 
00194     if (0 != thread_management_get_leader_address(interface_id, destination)) {
00195         return -2;
00196     }
00197 
00198     cur = protocol_stack_interface_info_get_by_id(interface_id);
00199     if (!cur || !cur->thread_info) {
00200         return -3;
00201     }
00202 
00203     this->router_id_cb_ptr = id_cb;
00204     ptr = payload;
00205     if (router_id < 0xfffe) {
00206         ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, router_id);
00207     }
00208     ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_MAC_ADDRESS, 8, mac);
00209 
00210     tr_debug("thread router id get id: %d, mac %s", router_id, trace_array(mac, 8));
00211 
00212     ptr = thread_tmfcop_tlv_data_write_uint8(ptr, TMFCOP_TLV_STATUS, status);
00213 
00214     return coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
00215                               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);
00216 }
00217 
00218 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)
00219 {
00220     thread_management_t *this = thread_management_find(interface_id);
00221     uint8_t payload[30];//!< max length 4 + 2, 4 + 8,  4 + 8,
00222     uint8_t destination[16];
00223     uint8_t *ptr;
00224 
00225     if (!this || !mac || router_id >= 0xfffe) {
00226         return -1;
00227     }
00228 
00229     if (0 != thread_management_get_leader_address(interface_id, destination)) {
00230         return -2;
00231     }
00232 
00233     this->router_id_release_cb_ptr = id_cb;
00234     ptr = payload;
00235     ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, router_id);
00236     ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_MAC_ADDRESS, 8, mac);
00237 
00238     tr_debug("thread router id release id: %d, mac %s", router_id, trace_array(mac, 8));
00239 
00240     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
00241                               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);
00242     return 0;
00243 }
00244 
00245 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)
00246 {
00247     thread_management_t *this = thread_management_find_by_service(service_id);
00248     (void) source_address;
00249     (void) source_port;
00250     if (!this) {
00251         return -1;
00252     }
00253 
00254     this->coap_asd_msg_id = 0; //clear the coap message id
00255 
00256     if (this->network_data_set_cb_ptr) {
00257         if (response_ptr) {
00258             // If we get response status is OK
00259             this->network_data_set_cb_ptr(this->interface_id, 0, response_ptr->payload_ptr, response_ptr->payload_len);
00260         } else {
00261             this->network_data_set_cb_ptr(this->interface_id, -1, NULL, 0);
00262         }
00263     }
00264 
00265     return 0;
00266 }
00267 
00268 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)
00269 {
00270     thread_management_t *this = thread_management_find(interface_id);
00271     uint8_t destination[16];
00272 
00273     if (!this) {
00274         return -1;
00275     }
00276 
00277     if (thread_management_get_leader_address(interface_id, destination)) {
00278         return -2;
00279     }
00280 
00281     this->network_data_set_cb_ptr = set_cb;
00282     tr_debug("thread network data send to %s", trace_ipv6(destination));
00283 
00284     this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
00285                               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);
00286 
00287     return 0;
00288 }
00289 
00290 int thread_management_client_network_data_unregister(int8_t interface_id, uint16_t rloc16)
00291 {
00292     thread_management_t *this = thread_management_find(interface_id);
00293     uint8_t payload[4];
00294     uint8_t *ptr;
00295     uint8_t destination[16];
00296 
00297     if (!this) {
00298         return -1;
00299     }
00300 
00301     if (thread_management_get_leader_address(interface_id, destination)) {
00302         return -2;
00303     }
00304     ptr = payload;
00305     ptr = thread_tmfcop_tlv_data_write_uint16(ptr,TMFCOP_TLV_RLOC16,rloc16);
00306 
00307     tr_debug("thread network data unregister");
00308 
00309     this->coap_asd_msg_id = coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
00310                               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);
00311     return 0;
00312 }
00313 
00314 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)
00315 {
00316     thread_management_t *this = thread_management_find_by_service(service_id);
00317     uint8_t *nd_data_options_ptr = NULL;
00318     int8_t status = -1;
00319     uint16_t nd_data_options_len = 0;
00320     (void) source_address;
00321     (void) source_port;
00322     if (!this) {
00323         return -1;
00324     }
00325 
00326     if (response_ptr) {
00327         status = 0; // If we get response status is OK
00328         nd_data_options_len = thread_meshcop_tlv_find(response_ptr->payload_ptr, response_ptr->payload_len, TMFCOP_TLV_ND_DATA, &nd_data_options_ptr);
00329     }
00330 
00331     if (this->neighbor_discovery_cb_ptr) {
00332         this->neighbor_discovery_cb_ptr(this->interface_id, status, nd_data_options_ptr, nd_data_options_len);
00333     }
00334 
00335     return 0;
00336 }
00337 
00338 int thread_management_client_get_interface_id_by_service_id(int8_t service_id)
00339 {
00340     thread_management_t *this = thread_management_find_by_service(service_id);
00341     if (!this) {
00342         return -1;
00343     }
00344     return this->interface_id;
00345 }
00346 
00347 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)
00348 {
00349     thread_management_t *this = thread_management_find(interface_id);
00350     uint8_t payload[2 + options_len]; //type + length + num of options
00351     uint8_t *ptr = &payload[2];
00352     uint8_t payload_len;
00353 
00354     if (!this || !options || options_len == 0) {
00355         return -1;
00356     }
00357 
00358     this->neighbor_discovery_cb_ptr = set_cb;
00359     tr_debug("thread neighbor discovery data request");
00360 
00361     memcpy(ptr, options, options_len);
00362     thread_tmfcop_tlv_data_write_header(payload, TMFCOP_TLV_ND_OPTION, options_len);
00363     payload_len = 2 + options_len; //type + length + options
00364 
00365     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, destination, THREAD_MANAGEMENT_PORT,
00366                               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);
00367     return 0;
00368 }
00369 
00370 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)
00371 {
00372     thread_management_t *this = thread_management_find_by_service(service_id);
00373     (void)source_address;
00374     (void)source_port;
00375     uint8_t state;
00376 
00377     tr_debug("Receiving active set response from leader");
00378 
00379     if(!this){
00380         return -1;
00381     }
00382 
00383     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id);
00384 
00385     if(!cur || !cur->thread_info){
00386         return -2;
00387     }
00388 
00389     if(!response_ptr || response_ptr->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED || !response_ptr->payload_ptr){
00390         tr_error("active set failed");
00391         goto getout;
00392     }
00393     if (1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &state) || state != 1) {
00394         tr_error("active set rejected");
00395         goto getout;
00396     }
00397     // TODO this is problematic we can not advertise before leader distributes the data
00398     // Current approach is to wait for leader
00399     // Spec says we could form own partition or just learn the older ones
00400     // We could then just clear timestamp from active set and learn new one.
00401     // thread_active_configuration_dataset_query_done(cur);
00402     return 0;
00403 
00404 getout:
00405 
00406     return 0;
00407 }
00408 
00409 int8_t thread_management_client_active_set(int8_t interface_id, uint8_t *dst_address)
00410 {
00411     thread_management_t *this = thread_management_find(interface_id);
00412     uint16_t response_len;
00413     uint8_t *response_ptr, *ptr;
00414     tr_debug("Sending active set to leader");
00415 
00416     response_len = thread_joiner_application_next_active_config_length(interface_id);
00417     if (!this || response_len < 1) {
00418         return -1;
00419     }
00420 
00421     response_ptr = ns_dyn_mem_alloc(response_len);
00422     if(!response_ptr) {
00423         tr_warn("Out of mem");
00424         return -2;
00425     }
00426     ptr = thread_joiner_application_next_active_config_write(interface_id, response_ptr);
00427 
00428     if (0 == coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, dst_address, THREAD_MANAGEMENT_PORT,
00429                               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)) {
00430         tr_warn("request send failed");
00431     }
00432     ns_dyn_mem_free(response_ptr);
00433     return 0;
00434 }
00435 
00436 
00437 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)
00438 {
00439     thread_management_t *this = thread_management_find_by_service(service_id);
00440     (void)source_address;
00441     (void)source_port;
00442     uint8_t state;
00443 
00444     tr_debug("Receiving pending set response from leader");
00445 
00446     if(!this){
00447         return -1;
00448     }
00449 
00450     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id);
00451 
00452     if(!cur || !cur->thread_info){
00453         return -2;
00454     }
00455 
00456     if(!response_ptr || response_ptr->coap_status == COAP_STATUS_BUILDER_MESSAGE_SENDING_FAILED || !response_ptr->payload_ptr){
00457         tr_error("pending set failed");
00458         goto getout;
00459     }
00460     if (1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &state) || state != 1) {
00461         tr_error("pending set rejected");
00462         goto getout;
00463     }
00464 
00465     return 0;
00466 
00467 getout:
00468     return 0;
00469 }
00470 
00471 int8_t thread_management_client_pending_set(int8_t interface_id, uint8_t *dst_address)
00472 {
00473     thread_management_t *this = thread_management_find(interface_id);
00474     uint16_t response_len;
00475     uint8_t *response_ptr, *ptr;
00476     tr_debug("Sending Pending set to leader");
00477 
00478     if (!this) {
00479         return -1;
00480     }
00481 
00482     response_len = thread_joiner_application_next_pending_config_length(interface_id);
00483 
00484     response_ptr = ns_dyn_mem_alloc(response_len);
00485     if(!response_ptr) {
00486         tr_warn("Out of mem");
00487         return -2;
00488     }
00489     ptr = thread_joiner_application_next_pending_config_build(interface_id,response_ptr);
00490 
00491     if (0 == coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, dst_address, THREAD_MANAGEMENT_PORT,
00492                               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)) {
00493         tr_warn("request send failed");
00494     }
00495     ns_dyn_mem_free(response_ptr);
00496     return 0;
00497 }
00498 
00499 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)
00500 {
00501     thread_management_t *this = thread_management_find_by_service(service_id);
00502     (void)source_address;
00503     (void)source_port;
00504     uint8_t state;
00505 
00506     tr_debug("Thread provisioning Received");
00507 
00508     if (!this) {
00509         return 0;
00510     }
00511 
00512     thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_NOT_DONE);
00513 
00514     // CoAP request timed out
00515     if(!response_ptr) {
00516         return 0;
00517     }
00518 
00519     if (response_ptr->msg_code != COAP_MSG_CODE_RESPONSE_CHANGED) {
00520         tr_error("Provisioning failed");
00521         thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_REJECTED);
00522         return 0;
00523     }
00524 
00525     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(this->interface_id);
00526 
00527     if(!cur || !cur->thread_info || 1 > thread_meshcop_tlv_data_get_uint8(response_ptr->payload_ptr, response_ptr->payload_len, MESHCOP_TLV_STATE, &state)){
00528         tr_error("provisioning response failed");
00529         return 0;
00530     }
00531     tr_debug("Thread provisioning status %d",state);
00532 
00533     if (state == 1) {
00534         thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_DONE);
00535     } else {
00536         thread_joiner_application_provisioning_set(this->interface_id, PROVISIONING_STATUS_REJECTED);
00537     }
00538 
00539     return 0;
00540 }
00541 
00542 int thread_management_client_provision_request(int8_t interface_id, uint8_t *dst_address, uint16_t port)
00543 {
00544     thread_management_t *this;
00545     uint8_t *ptr, *data_ptr;
00546     uint16_t length;
00547 
00548     if (thread_joiner_application_provisioning_get(interface_id) == PROVISIONING_STATUS_ONGOING) {
00549         // wait for response to to the message
00550         return 0;
00551     }
00552 
00553     tr_debug("Thread provisioning start send");
00554     this = thread_management_find(interface_id);
00555     device_configuration_s *device_configuration_ptr = thread_joiner_application_get_device_config(interface_id);
00556 
00557     if(!this || !device_configuration_ptr) {
00558         return -1;
00559     }
00560     length = thread_joiner_application_device_configuration_length(device_configuration_ptr);
00561     length += 3;// State
00562 
00563     data_ptr = ptr = ns_dyn_mem_alloc(length);
00564     if (!ptr) {
00565         tr_error("Failed to start Commissioning");
00566         return -1;
00567     }
00568     ptr = thread_joiner_application_device_configuration_build(ptr, device_configuration_ptr);
00569     ptr = thread_tmfcop_tlv_data_write_uint8(ptr, MESHCOP_TLV_STATE, 1);
00570 
00571 
00572     thread_joiner_application_provisioning_set(interface_id, PROVISIONING_STATUS_ONGOING);
00573 
00574     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE, dst_address, port,
00575                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST, THREAD_URI_JOINER_APPLICATION_REQUEST, COAP_CT_OCTET_STREAM,
00576                               data_ptr, ptr - data_ptr, thread_management_client_provision_request_cb);
00577 
00578     ns_dyn_mem_free(data_ptr);
00579 
00580     return 0;
00581 }
00582 
00583 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)
00584 {
00585     (void) service_id;
00586     (void) source_address;
00587     (void) source_port;
00588     (void) response_ptr;
00589     return 0;
00590 }
00591 
00592 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])
00593 {
00594     thread_management_t *this = thread_management_find(interface_id);
00595     protocol_interface_info_entry_t *cur = protocol_stack_interface_info_get_by_id(interface_id);
00596 
00597     if (!this || !cur) {
00598         tr_warn("No resolution client or protocol info!");
00599         return;
00600     }
00601 
00602     tr_debug("Thread resolution client; proactive address notification");
00603 
00604     uint8_t payload[2 + 16 + 2 + 2 + 2 + 8];
00605     uint8_t *ptr;
00606 
00607     ptr = payload;
00608     ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_TARGET_EID, 16, address);
00609     ptr = thread_tmfcop_tlv_data_write_uint16(ptr, TMFCOP_TLV_RLOC16, rloc);
00610     ptr = thread_tmfcop_tlv_data_write(ptr, TMFCOP_TLV_ML_EID, 8, ml_eid);
00611 
00612     coap_service_request_send(this->coap_service_id, COAP_REQUEST_OPTIONS_NONE,
00613                               dst_addr, THREAD_MANAGEMENT_PORT,
00614                               COAP_MSG_TYPE_CONFIRMABLE, COAP_MSG_CODE_REQUEST_POST,
00615                               THREAD_URI_ADDRESS_NOTIFICATION, COAP_CT_OCTET_STREAM,
00616                               payload, ptr - payload, thread_management_client_proactive_an_cb);
00617 }
00618 
00619 void thread_management_client_pending_coap_request_kill(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_active = false;
00629 
00630     if (this->coap_asd_msg_id != 0) {
00631         coap_service_request_delete(this->coap_service_id, this->coap_asd_msg_id);
00632         this->coap_asd_msg_id = 0;
00633     }
00634 
00635     if (cur->thread_info->routerIdReqCoapID != 0) {
00636         coap_service_request_delete(this->coap_service_id, cur->thread_info->routerIdReqCoapID);
00637         cur->thread_info->routerIdReqCoapID = 0;
00638     }
00639 }
00640 
00641 #endif