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