xref: /btstack/src/mesh/mesh_access.c (revision 94dc8eb321a7f7f0a210fd842516b5c13a7033ec)
1 /*
2  * Copyright (C) 2019 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define __BTSTACK_FILE__ "mesh_access.c"
39 
40 #include <string.h>
41 #include <stdio.h>
42 #include <stdarg.h>
43 
44 #include "mesh/mesh_access.h"
45 
46 #include "btstack_debug.h"
47 #include "btstack_memory.h"
48 #include "btstack_tlv.h"
49 
50 #include "mesh/beacon.h"
51 #include "mesh/mesh_foundation.h"
52 #include "mesh/mesh_iv_index_seq_number.h"
53 #include "mesh/mesh_node.h"
54 #include "mesh/mesh_proxy.h"
55 #include "mesh/mesh_upper_transport.h"
56 
57 #define MEST_TRANSACTION_TIMEOUT_MS  6000
58 
59 static void mesh_access_message_process_handler(mesh_pdu_t * pdu);
60 static void mesh_access_secure_network_beacon_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size);
61 static void mesh_access_upper_transport_handler(mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu);
62 static const mesh_operation_t * mesh_model_lookup_operation_by_opcode(mesh_model_t * model, uint32_t opcode);
63 static void mesh_persist_iv_index_and_sequence_number(void);
64 
65 // acknowledged messages
66 static btstack_linked_list_t  mesh_access_acknowledged_messages;
67 static btstack_timer_source_t mesh_access_acknowledged_timer;
68 
69 static uint16_t mid_counter;
70 
71 static const btstack_tlv_t * btstack_tlv_singleton_impl;
72 static void *                btstack_tlv_singleton_context;
73 
74 // Transitions
75 static btstack_linked_list_t  transitions;
76 static btstack_timer_source_t transitions_timer;
77 static uint32_t transition_step_min_ms;
78 static uint8_t mesh_transaction_id_counter = 0;
79 
80 static void mesh_access_setup_tlv(void){
81     if (btstack_tlv_singleton_impl) return;
82     btstack_tlv_get_instance(&btstack_tlv_singleton_impl, &btstack_tlv_singleton_context);
83 }
84 
85 void mesh_access_init(void){
86     // register with upper transport
87     mesh_upper_transport_register_access_message_handler(&mesh_access_message_process_handler);
88     mesh_upper_transport_set_higher_layer_handler(&mesh_access_upper_transport_handler);
89 
90     // register for secure network beacons
91     beacon_register_for_secure_network_beacons(&mesh_access_secure_network_beacon_handler);
92 
93     // register for seq number updates
94     mesh_sequence_number_set_update_callback(&mesh_persist_iv_index_and_sequence_number);
95 }
96 
97 void mesh_access_emit_state_update_bool(btstack_packet_handler_t * event_handler, uint8_t element_index, uint32_t model_identifier,
98     model_state_id_t state_identifier, model_state_update_reason_t reason, uint8_t value){
99     if (event_handler == NULL) return;
100     uint8_t event[14] = {HCI_EVENT_MESH_META, 13, MESH_SUBEVENT_STATE_UPDATE_BOOL};
101     int pos = 3;
102     event[pos++] = element_index;
103     little_endian_store_32(event, pos, model_identifier);
104     pos += 4;
105     little_endian_store_32(event, pos, (uint32_t)state_identifier);
106     pos += 4;
107     event[pos++] = (uint8_t)reason;
108     event[pos++] = value;
109     (*event_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
110 }
111 
112 void mesh_access_emit_state_update_int16(btstack_packet_handler_t * event_handler, uint8_t element_index, uint32_t model_identifier,
113     model_state_id_t state_identifier, model_state_update_reason_t reason, int16_t value){
114     if (event_handler == NULL) return;
115     uint8_t event[14] = {HCI_EVENT_MESH_META, 13, MESH_SUBEVENT_STATE_UPDATE_BOOL};
116     int pos = 3;
117     event[pos++] = element_index;
118     little_endian_store_32(event, pos, model_identifier);
119     pos += 4;
120     little_endian_store_32(event, pos, (uint32_t)state_identifier);
121     pos += 4;
122     event[pos++] = (uint8_t)reason;
123     little_endian_store_16(event, pos, (uint16_t) value);
124     pos += 2;
125     (*event_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
126 }
127 
128 uint8_t mesh_access_acknowledged_message_retransmissions(void){
129     return 3;
130 }
131 
132 uint32_t mesh_access_acknowledged_message_timeout_ms(void){
133     return 30000;
134 }
135 
136 #define MESH_ACCESS_OPCODE_INVALID 0xFFFFFFFFu
137 
138 void mesh_access_send_unacknowledged_pdu(mesh_pdu_t * pdu){
139     pdu->ack_opcode = MESH_ACCESS_OPCODE_INVALID;;
140     mesh_upper_transport_send_access_pdu(pdu);
141 }
142 
143 void mesh_access_send_acknowledged_pdu(mesh_pdu_t * pdu, uint8_t retransmissions, uint32_t ack_opcode){
144     pdu->retransmit_count = retransmissions;
145     pdu->ack_opcode = ack_opcode;
146 
147     mesh_upper_transport_send_access_pdu(pdu);
148 }
149 
150 #define MESH_SUBEVENT_MESSAGE_NOT_ACKNOWLEDGED                                        0x30
151 
152 static void mesh_access_acknowledged_run(btstack_timer_source_t * ts){
153     UNUSED(ts);
154 
155     uint32_t now = btstack_run_loop_get_time_ms();
156 
157     // handle timeouts
158     btstack_linked_list_iterator_t ack_it;
159     btstack_linked_list_iterator_init(&ack_it, &mesh_access_acknowledged_messages);
160     while (btstack_linked_list_iterator_has_next(&ack_it)){
161         mesh_pdu_t * pdu = (mesh_pdu_t *) btstack_linked_list_iterator_next(&ack_it);
162         if (btstack_time_delta(now, pdu->retransmit_timeout_ms) >= 0) {
163             // remove from list
164             btstack_linked_list_remove(&mesh_access_acknowledged_messages, (btstack_linked_item_t*) pdu);
165             // retransmit or report failure
166             if (pdu->retransmit_count){
167                 pdu->retransmit_count--;
168                 mesh_upper_transport_send_access_pdu(pdu);
169             } else {
170                 // find correct model and emit error
171                 uint16_t src = mesh_pdu_src(pdu);
172                 uint16_t dst = mesh_pdu_dst(pdu);
173                 mesh_element_t * element = mesh_node_element_for_unicast_address(src);
174                 if (element){
175                     // find
176                     mesh_model_iterator_t model_it;
177                     mesh_model_iterator_init(&model_it, element);
178                     while (mesh_model_iterator_has_next(&model_it)){
179                         mesh_model_t * model = mesh_model_iterator_next(&model_it);
180                         // find opcode in table
181                         const mesh_operation_t * operation = mesh_model_lookup_operation_by_opcode(model, pdu->ack_opcode);
182                         if (operation == NULL) continue;
183                         if (model->model_packet_handler == NULL) continue;
184                         // emit event
185                         uint8_t event[13];
186                         event[0] = HCI_EVENT_MESH_META;
187                         event[1] = sizeof(event) - 2;
188                         event[2] = element->element_index;
189                         little_endian_store_32(event, 3, model->model_identifier);
190                         little_endian_store_32(event, 7, pdu->ack_opcode);
191                         little_endian_store_16(event, 11, dst);
192                         (*model->model_packet_handler)(HCI_EVENT_PACKET, 0, event, sizeof(event));
193                     }
194                 }
195 
196                 // free
197                 mesh_upper_transport_pdu_free(pdu);
198             }
199         }
200     }
201 
202     // find earliest timeout and set timer
203     btstack_linked_list_iterator_init(&ack_it, &mesh_access_acknowledged_messages);
204     int32_t next_timeout_ms = 0;
205     while (btstack_linked_list_iterator_has_next(&ack_it)){
206         mesh_pdu_t * pdu = (mesh_pdu_t *) btstack_linked_list_iterator_next(&ack_it);
207         int32_t timeout_delta_ms = btstack_time_delta(pdu->retransmit_timeout_ms, now);
208         if (next_timeout_ms == 0 || timeout_delta_ms < next_timeout_ms){
209             next_timeout_ms = timeout_delta_ms;
210         }
211     }
212 
213     // set timer
214     if (next_timeout_ms == 0) return;
215 
216     btstack_run_loop_set_timer(&mesh_access_acknowledged_timer, next_timeout_ms);
217     btstack_run_loop_set_timer_handler(&mesh_access_acknowledged_timer, mesh_access_acknowledged_run);
218     btstack_run_loop_add_timer(&mesh_access_acknowledged_timer);
219 }
220 
221 static void mesh_access_acknowledged_received(uint16_t rx_src, uint32_t opcode){
222     // check if received src matches our dest
223     // free acknowledged messages if we were waiting for this message
224 
225     btstack_linked_list_iterator_t ack_it;
226     btstack_linked_list_iterator_init(&ack_it, &mesh_access_acknowledged_messages);
227     while (btstack_linked_list_iterator_has_next(&ack_it)){
228         mesh_pdu_t * tx_pdu = (mesh_pdu_t *) btstack_linked_list_iterator_next(&ack_it);
229         uint16_t tx_dest = mesh_pdu_dst(tx_pdu);
230         if (tx_dest != rx_src) continue;
231         if (tx_pdu->ack_opcode != opcode) continue;
232         // got expected response from dest, remove from outgoing messages
233         mesh_upper_transport_pdu_free(tx_pdu);
234         return;
235     }
236 }
237 
238 static void mesh_access_upper_transport_handler(mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu){
239     switch (callback_type){
240         case MESH_TRANSPORT_PDU_SENT:
241             // unacknowledged -> free
242             if (pdu->ack_opcode == MESH_ACCESS_OPCODE_INVALID){
243                 mesh_upper_transport_pdu_free(pdu);
244                 break;
245             }
246             // setup timeout
247             pdu->retransmit_timeout_ms = btstack_run_loop_get_time_ms() + mesh_access_acknowledged_message_timeout_ms();
248             // add to mesh_access_acknowledged_messages
249             btstack_linked_list_add(&mesh_access_acknowledged_messages, (btstack_linked_item_t *) pdu);
250             // update timer
251             mesh_access_acknowledged_run(NULL);
252             break;
253         default:
254             break;
255     }
256 }
257 
258 // Mesh Model Transitions
259 
260 void mesh_access_transitions_setup_transaction(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address){
261     transition->transaction_timestamp_ms = btstack_run_loop_get_time_ms();
262     transition->transaction_identifier = transaction_identifier;
263     transition->src_address = src_address;
264     transition->dst_address = dst_address;
265 }
266 
267 void mesh_access_transitions_abort_transaction(mesh_transition_t * transition){
268     mesh_access_transitions_remove(transition);
269 }
270 
271 
272 static int mesh_access_transitions_transaction_is_expired(mesh_transition_t * transition){
273     return (btstack_run_loop_get_time_ms() - transition->transaction_timestamp_ms) > MEST_TRANSACTION_TIMEOUT_MS;
274 }
275 
276 mesh_transaction_status_t mesh_access_transitions_transaction_status(mesh_transition_t * transition, uint8_t transaction_identifier, uint16_t src_address, uint16_t dst_address){
277     if (transition->src_address != src_address || transition->dst_address != dst_address) return MESH_TRANSACTION_STATUS_DIFFERENT_DST_OR_SRC;
278 
279     if (transition->transaction_identifier == transaction_identifier && !mesh_access_transitions_transaction_is_expired(transition)){
280             return MESH_TRANSACTION_STATUS_RETRANSMISSION;
281     }
282     return MESH_TRANSACTION_STATUS_NEW;
283 }
284 
285 uint8_t mesh_access_transitions_num_steps_from_gdtt(uint8_t time_gdtt){
286     return time_gdtt >> 2;
287 }
288 
289 static uint32_t mesh_access_transitions_step_ms_from_gdtt(uint8_t time_gdtt){
290     mesh_default_transition_step_resolution_t step_resolution = (mesh_default_transition_step_resolution_t) (time_gdtt & 0x03u);
291     switch (step_resolution){
292         case MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_100ms:
293             return 100;
294         case MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_1s:
295             return 1000;
296         case MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_10s:
297             return 10000;
298         case MESH_DEFAULT_TRANSITION_STEP_RESOLUTION_10min:
299             return 600000;
300         default:
301             return 0;
302     }
303 }
304 
305 uint32_t mesh_access_time_gdtt2ms(uint8_t time_gdtt){
306     uint8_t num_steps  = mesh_access_transitions_num_steps_from_gdtt(time_gdtt);
307     if (num_steps > 0x3E) return 0;
308 
309     return mesh_access_transitions_step_ms_from_gdtt(time_gdtt) * num_steps;
310 }
311 
312 static void mesh_access_transitions_timeout_handler(btstack_timer_source_t * timer){
313     btstack_linked_list_iterator_t it;
314     btstack_linked_list_iterator_init(&it, &transitions);
315     while (btstack_linked_list_iterator_has_next(&it)){
316         mesh_transition_t * transition = (mesh_transition_t *)btstack_linked_list_iterator_next(&it);
317         (transition->transition_callback)(transition, TRANSITION_UPDATE, btstack_run_loop_get_time_ms());
318     }
319     if (btstack_linked_list_empty(&transitions)) return;
320 
321     btstack_run_loop_set_timer(timer, transition_step_min_ms);
322     btstack_run_loop_add_timer(timer);
323 }
324 
325 static void mesh_access_transitions_timer_start(void){
326     btstack_run_loop_remove_timer(&transitions_timer);
327     btstack_run_loop_set_timer_handler(&transitions_timer, mesh_access_transitions_timeout_handler);
328     btstack_run_loop_set_timer(&transitions_timer, transition_step_min_ms);
329     btstack_run_loop_add_timer(&transitions_timer);
330 }
331 
332 static void mesh_access_transitions_timer_stop(void){
333     btstack_run_loop_remove_timer(&transitions_timer);
334 }
335 
336 static uint32_t mesh_access_transitions_get_step_min_ms(void){
337     uint32_t min_timeout_ms = 0;
338 
339     btstack_linked_list_iterator_t it;
340     btstack_linked_list_iterator_init(&it, &transitions);
341     while (btstack_linked_list_iterator_has_next(&it)){
342         mesh_transition_t * transition = (mesh_transition_t *)btstack_linked_list_iterator_next(&it);
343         if (min_timeout_ms == 0 || transition->step_duration_ms < min_timeout_ms){
344             min_timeout_ms = transition->step_duration_ms;
345         }
346     }
347     return min_timeout_ms;
348 }
349 
350 void mesh_access_transitions_setup(mesh_transition_t * transition, mesh_model_t * mesh_model,
351     uint8_t transition_time_gdtt, uint8_t delay_gdtt,
352     void (* transition_callback)(struct mesh_transition * transition, transition_event_t event, uint32_t current_timestamp)){
353 
354     //  Only values of 0x00 through 0x3E shall be used to specify the value of the Transition Number of Steps field
355     uint8_t num_steps  = mesh_access_transitions_num_steps_from_gdtt(transition_time_gdtt);
356     if (num_steps > 0x3E) return;
357 
358     transition->state = MESH_TRANSITION_STATE_IDLE;
359     transition->phase_start_ms = 0;
360 
361     transition->mesh_model = mesh_model;
362     transition->transition_callback = transition_callback;
363     transition->step_duration_ms = mesh_access_transitions_step_ms_from_gdtt(transition_time_gdtt);
364     transition->remaining_delay_time_ms = delay_gdtt * 5;
365     transition->remaining_transition_time_ms = num_steps * transition->step_duration_ms;
366 }
367 
368 void mesh_access_transitions_add(mesh_transition_t * transition){
369     if (transition->step_duration_ms == 0) return;
370 
371     if (btstack_linked_list_empty(&transitions) || transition->step_duration_ms < transition_step_min_ms){
372         transition_step_min_ms = transition->step_duration_ms;
373     }
374     mesh_access_transitions_timer_start();
375     btstack_linked_list_add(&transitions, (btstack_linked_item_t *) transition);
376     (transition->transition_callback)(transition, TRANSITION_START, btstack_run_loop_get_time_ms());
377 }
378 
379 void mesh_access_transitions_remove(mesh_transition_t * transition){
380     mesh_access_transitions_setup(transition, NULL, 0, 0, NULL);
381     btstack_linked_list_remove(&transitions, (btstack_linked_item_t *) transition);
382 
383     if (btstack_linked_list_empty(&transitions)){
384         mesh_access_transitions_timer_stop();
385     } else {
386         transition_step_min_ms = mesh_access_transitions_get_step_min_ms();
387     }
388 }
389 
390 uint8_t mesh_access_transactions_get_next_transaction_id(void){
391     mesh_transaction_id_counter++;
392     if (mesh_transaction_id_counter == 0){
393         mesh_transaction_id_counter = 1;
394     }
395     return mesh_transaction_id_counter;
396 }
397 
398 // Mesh Node Element functions
399 uint8_t mesh_access_get_element_index(mesh_model_t * mesh_model){
400     return mesh_model->element->element_index;
401 }
402 
403 uint16_t mesh_access_get_element_address(mesh_model_t * mesh_model){
404     return mesh_node_get_primary_element_address() + mesh_model->element->element_index;
405 }
406 
407 // Model Identifier utilities
408 
409 uint32_t mesh_model_get_model_identifier(uint16_t vendor_id, uint16_t model_id){
410     return (vendor_id << 16) | model_id;
411 }
412 
413 uint32_t mesh_model_get_model_identifier_bluetooth_sig(uint16_t model_id){
414     return (BLUETOOTH_COMPANY_ID_BLUETOOTH_SIG_INC << 16) | model_id;
415 }
416 
417 uint16_t mesh_model_get_model_id(uint32_t model_identifier){
418     return model_identifier & 0xFFFFu;
419 }
420 
421 uint16_t mesh_model_get_vendor_id(uint32_t model_identifier){
422     return model_identifier >> 16;
423 }
424 
425 int mesh_model_is_bluetooth_sig(uint32_t model_identifier){
426     return mesh_model_get_vendor_id(model_identifier) == BLUETOOTH_COMPANY_ID_BLUETOOTH_SIG_INC;
427 }
428 
429 mesh_model_t * mesh_model_get_configuration_server(void){
430     return mesh_model_get_by_identifier(mesh_node_get_primary_element(), mesh_model_get_model_identifier_bluetooth_sig(MESH_SIG_MODEL_ID_CONFIGURATION_SERVER));
431 }
432 
433 void mesh_element_add_model(mesh_element_t * element, mesh_model_t * mesh_model){
434     if (mesh_model_is_bluetooth_sig(mesh_model->model_identifier)){
435         element->models_count_sig++;
436     } else {
437         element->models_count_vendor++;
438     }
439     mesh_model->mid = mid_counter++;
440     mesh_model->element = element;
441     btstack_linked_list_add_tail(&element->models, (btstack_linked_item_t *) mesh_model);
442 }
443 
444 void mesh_model_iterator_init(mesh_model_iterator_t * iterator, mesh_element_t * element){
445     btstack_linked_list_iterator_init(&iterator->it, &element->models);
446 }
447 
448 int mesh_model_iterator_has_next(mesh_model_iterator_t * iterator){
449     return btstack_linked_list_iterator_has_next(&iterator->it);
450 }
451 
452 mesh_model_t * mesh_model_iterator_next(mesh_model_iterator_t * iterator){
453     return (mesh_model_t *) btstack_linked_list_iterator_next(&iterator->it);
454 }
455 
456 mesh_model_t * mesh_model_get_by_identifier(mesh_element_t * element, uint32_t model_identifier){
457     mesh_model_iterator_t it;
458     mesh_model_iterator_init(&it, element);
459     while (mesh_model_iterator_has_next(&it)){
460         mesh_model_t * model = mesh_model_iterator_next(&it);
461         if (model->model_identifier != model_identifier) continue;
462         return model;
463     }
464     return NULL;
465 }
466 
467 mesh_model_t * mesh_access_model_for_address_and_model_identifier(uint16_t element_address, uint32_t model_identifier, uint8_t * status){
468     mesh_element_t * element = mesh_node_element_for_unicast_address(element_address);
469     if (element == NULL){
470         *status = MESH_FOUNDATION_STATUS_INVALID_ADDRESS;
471         return NULL;
472     }
473     mesh_model_t * model = mesh_model_get_by_identifier(element, model_identifier);
474     if (model == NULL) {
475         *status = MESH_FOUNDATION_STATUS_INVALID_MODEL;
476     } else {
477         *status = MESH_FOUNDATION_STATUS_SUCCESS;
478     }
479     return model;
480 }
481 
482 uint16_t mesh_pdu_src(mesh_pdu_t * pdu){
483     switch (pdu->pdu_type){
484         case MESH_PDU_TYPE_TRANSPORT:
485             return mesh_transport_src((mesh_transport_pdu_t*) pdu);
486         case MESH_PDU_TYPE_NETWORK:
487             return mesh_network_src((mesh_network_pdu_t *) pdu);
488         default:
489             return MESH_ADDRESS_UNSASSIGNED;
490     }
491 }
492 
493 uint16_t mesh_pdu_dst(mesh_pdu_t * pdu){
494     switch (pdu->pdu_type){
495         case MESH_PDU_TYPE_TRANSPORT:
496             return mesh_transport_dst((mesh_transport_pdu_t*) pdu);
497         case MESH_PDU_TYPE_NETWORK:
498             return mesh_network_dst((mesh_network_pdu_t *) pdu);
499         default:
500             return MESH_ADDRESS_UNSASSIGNED;
501     }
502 }
503 
504 uint16_t mesh_pdu_netkey_index(mesh_pdu_t * pdu){
505     switch (pdu->pdu_type){
506         case MESH_PDU_TYPE_TRANSPORT:
507             return ((mesh_transport_pdu_t*) pdu)->netkey_index;
508         case MESH_PDU_TYPE_NETWORK:
509             return ((mesh_network_pdu_t *) pdu)->netkey_index;
510         default:
511             return 0;
512     }
513 }
514 
515 uint16_t mesh_pdu_appkey_index(mesh_pdu_t * pdu){
516     switch (pdu->pdu_type){
517         case MESH_PDU_TYPE_TRANSPORT:
518             return ((mesh_transport_pdu_t*) pdu)->appkey_index;
519         case MESH_PDU_TYPE_NETWORK:
520             return ((mesh_network_pdu_t *) pdu)->appkey_index;
521         default:
522             return 0;
523     }
524 }
525 
526 uint16_t mesh_pdu_len(mesh_pdu_t * pdu){
527     switch (pdu->pdu_type){
528         case MESH_PDU_TYPE_TRANSPORT:
529             return ((mesh_transport_pdu_t*) pdu)->len;
530         case MESH_PDU_TYPE_NETWORK:
531             return ((mesh_network_pdu_t *) pdu)->len - 10;
532         default:
533             return 0;
534     }
535 }
536 
537 uint8_t * mesh_pdu_data(mesh_pdu_t * pdu){
538     switch (pdu->pdu_type){
539         case MESH_PDU_TYPE_TRANSPORT:
540             return ((mesh_transport_pdu_t*) pdu)->data;
541         case MESH_PDU_TYPE_NETWORK:
542             return &((mesh_network_pdu_t *) pdu)->data[10];
543         default:
544             return NULL;
545     }
546 }
547 
548 // message parser
549 
550 static int mesh_access_get_opcode(uint8_t * buffer, uint16_t buffer_size, uint32_t * opcode, uint16_t * opcode_size){
551     switch (buffer[0] >> 6){
552         case 0:
553         case 1:
554             if (buffer[0] == 0x7f) return 0;
555             *opcode = buffer[0];
556             *opcode_size = 1;
557             return 1;
558         case 2:
559             if (buffer_size < 2) return 0;
560             *opcode = big_endian_read_16(buffer, 0);
561             *opcode_size = 2;
562             return 1;
563         case 3:
564             if (buffer_size < 3) return 0;
565             *opcode = (buffer[0] << 16) | little_endian_read_16(buffer, 1);
566             *opcode_size = 3;
567             return 1;
568         default:
569             return 0;
570     }
571 }
572 
573 static int mesh_access_transport_get_opcode(mesh_transport_pdu_t * transport_pdu, uint32_t * opcode, uint16_t * opcode_size){
574     return mesh_access_get_opcode(transport_pdu->data, transport_pdu->len, opcode, opcode_size);
575 }
576 
577 static int mesh_access_network_get_opcode(mesh_network_pdu_t * network_pdu, uint32_t * opcode, uint16_t * opcode_size){
578     // TransMIC already removed by mesh_upper_transport_validate_unsegmented_message_ccm
579     return mesh_access_get_opcode(&network_pdu->data[10], network_pdu->len - 10, opcode, opcode_size);
580 }
581 
582 int mesh_access_pdu_get_opcode(mesh_pdu_t * pdu, uint32_t * opcode, uint16_t * opcode_size){
583     switch (pdu->pdu_type){
584         case MESH_PDU_TYPE_TRANSPORT:
585             return mesh_access_transport_get_opcode((mesh_transport_pdu_t*) pdu, opcode, opcode_size);
586         case MESH_PDU_TYPE_NETWORK:
587             return mesh_access_network_get_opcode((mesh_network_pdu_t *) pdu, opcode, opcode_size);
588         default:
589             return 0;
590     }
591 }
592 
593 void mesh_access_parser_skip(mesh_access_parser_state_t * state, uint16_t bytes_to_skip){
594     state->data += bytes_to_skip;
595     state->len  -= bytes_to_skip;
596 }
597 
598 int mesh_access_parser_init(mesh_access_parser_state_t * state, mesh_pdu_t * pdu){
599     state->data = mesh_pdu_data(pdu);
600     state->len  = mesh_pdu_len(pdu);
601 
602     uint16_t opcode_size = 0;
603     int ok = mesh_access_get_opcode(state->data, state->len, &state->opcode, &opcode_size);
604     if (ok){
605         mesh_access_parser_skip(state, opcode_size);
606     }
607     return ok;
608 }
609 
610 uint16_t mesh_access_parser_available(mesh_access_parser_state_t * state){
611     return state->len;
612 }
613 
614 uint8_t mesh_access_parser_get_u8(mesh_access_parser_state_t * state){
615     uint8_t value = *state->data;
616     mesh_access_parser_skip(state, 1);
617     return value;
618 }
619 
620 uint16_t mesh_access_parser_get_u16(mesh_access_parser_state_t * state){
621     uint16_t value = little_endian_read_16(state->data, 0);
622     mesh_access_parser_skip(state, 2);
623     return value;
624 }
625 
626 uint32_t mesh_access_parser_get_u24(mesh_access_parser_state_t * state){
627     uint32_t value = little_endian_read_24(state->data, 0);
628     mesh_access_parser_skip(state, 3);
629     return value;
630 }
631 
632 uint32_t mesh_access_parser_get_u32(mesh_access_parser_state_t * state){
633     uint32_t value = little_endian_read_24(state->data, 0);
634     mesh_access_parser_skip(state, 4);
635     return value;
636 }
637 
638 void mesh_access_parser_get_u128(mesh_access_parser_state_t * state, uint8_t * dest){
639     reverse_128( state->data, dest);
640     mesh_access_parser_skip(state, 16);
641 }
642 
643 void mesh_access_parser_get_label_uuid(mesh_access_parser_state_t * state, uint8_t * dest){
644     memcpy( dest, state->data, 16);
645     mesh_access_parser_skip(state, 16);
646 }
647 
648 void mesh_access_parser_get_key(mesh_access_parser_state_t * state, uint8_t * dest){
649     memcpy( dest, state->data, 16);
650     mesh_access_parser_skip(state, 16);
651 }
652 
653 uint32_t mesh_access_parser_get_model_identifier(mesh_access_parser_state_t * parser){
654     if (mesh_access_parser_available(parser) == 4){
655         return mesh_access_parser_get_u32(parser);
656     } else {
657         return (BLUETOOTH_COMPANY_ID_BLUETOOTH_SIG_INC << 16) | mesh_access_parser_get_u16(parser);
658     }
659 }
660 
661 // Mesh Access Message Builder
662 
663 // message builder
664 
665 static int mesh_access_setup_opcode(uint8_t * buffer, uint32_t opcode){
666     if (opcode < 0x100){
667         buffer[0] = opcode;
668         return 1;
669     }
670     if (opcode < 0x10000){
671         big_endian_store_16(buffer, 0, opcode);
672         return 2;
673     }
674     buffer[0] = opcode >> 16;
675     little_endian_store_16(buffer, 1, opcode & 0xffff);
676     return 3;
677 }
678 
679 mesh_transport_pdu_t * mesh_access_transport_init(uint32_t opcode){
680     mesh_transport_pdu_t * pdu = mesh_transport_pdu_get();
681     if (!pdu) return NULL;
682 
683     pdu->len  = mesh_access_setup_opcode(pdu->data, opcode);
684     return pdu;
685 }
686 
687 void mesh_access_transport_add_uint8(mesh_transport_pdu_t * pdu, uint8_t value){
688     pdu->data[pdu->len++] = value;
689 }
690 
691 void mesh_access_transport_add_uint16(mesh_transport_pdu_t * pdu, uint16_t value){
692     little_endian_store_16(pdu->data, pdu->len, value);
693     pdu->len += 2;
694 }
695 
696 void mesh_access_transport_add_uint24(mesh_transport_pdu_t * pdu, uint32_t value){
697     little_endian_store_24(pdu->data, pdu->len, value);
698     pdu->len += 3;
699 }
700 
701 void mesh_access_transport_add_uint32(mesh_transport_pdu_t * pdu, uint32_t value){
702     little_endian_store_32(pdu->data, pdu->len, value);
703     pdu->len += 4;
704 }
705 void mesh_access_transport_add_model_identifier(mesh_transport_pdu_t * pdu, uint32_t model_identifier){
706     if (mesh_model_is_bluetooth_sig(model_identifier)){
707         mesh_access_transport_add_uint16( pdu, mesh_model_get_model_id(model_identifier) );
708     } else {
709         mesh_access_transport_add_uint32( pdu, model_identifier );
710     }
711 }
712 
713 mesh_network_pdu_t * mesh_access_network_init(uint32_t opcode){
714     mesh_network_pdu_t * pdu = mesh_network_pdu_get();
715     if (!pdu) return NULL;
716 
717     pdu->len  = mesh_access_setup_opcode(&pdu->data[10], opcode) + 10;
718     return pdu;
719 }
720 
721 void mesh_access_network_add_uint8(mesh_network_pdu_t * pdu, uint8_t value){
722     pdu->data[pdu->len++] = value;
723 }
724 
725 void mesh_access_network_add_uint16(mesh_network_pdu_t * pdu, uint16_t value){
726     little_endian_store_16(pdu->data, pdu->len, value);
727     pdu->len += 2;
728 }
729 
730 void mesh_access_network_add_uint24(mesh_network_pdu_t * pdu, uint16_t value){
731     little_endian_store_24(pdu->data, pdu->len, value);
732     pdu->len += 3;
733 }
734 
735 void mesh_access_network_add_uint32(mesh_network_pdu_t * pdu, uint16_t value){
736     little_endian_store_32(pdu->data, pdu->len, value);
737     pdu->len += 4;
738 }
739 
740 void mesh_access_network_add_model_identifier(mesh_network_pdu_t * pdu, uint32_t model_identifier){
741     if (mesh_model_is_bluetooth_sig(model_identifier)){
742         mesh_access_network_add_uint16( pdu, mesh_model_get_model_id(model_identifier) );
743     } else {
744         mesh_access_network_add_uint32( pdu, model_identifier );
745     }
746 }
747 
748 // access message template
749 
750 mesh_network_pdu_t * mesh_access_setup_unsegmented_message(const mesh_access_message_t *template, ...){
751     mesh_network_pdu_t * network_pdu = mesh_access_network_init(template->opcode);
752     if (!network_pdu) return NULL;
753 
754     va_list argptr;
755     va_start(argptr, template);
756 
757     // add params
758     const char * format = template->format;
759     uint16_t word;
760     uint32_t longword;
761     while (*format){
762         switch (*format){
763             case '1':
764                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
765                 mesh_access_network_add_uint8( network_pdu, word);
766                 break;
767             case '2':
768                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
769                 mesh_access_network_add_uint16( network_pdu, word);
770                 break;
771             case '3':
772                 longword = va_arg(argptr, uint32_t);
773                 mesh_access_network_add_uint24( network_pdu, longword);
774                 break;
775             case '4':
776                 longword = va_arg(argptr, uint32_t);
777                 mesh_access_network_add_uint32( network_pdu, longword);
778                 break;
779             case 'm':
780                 longword = va_arg(argptr, uint32_t);
781                 mesh_access_network_add_model_identifier( network_pdu, longword);
782                 break;
783             default:
784                 log_error("Unsupported mesh message format specifier '%c", *format);
785                 break;
786         }
787         format++;
788     }
789 
790     va_end(argptr);
791 
792     return network_pdu;
793 }
794 
795 mesh_transport_pdu_t * mesh_access_setup_segmented_message(const mesh_access_message_t *template, ...){
796     mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(template->opcode);
797     if (!transport_pdu) return NULL;
798 
799     va_list argptr;
800     va_start(argptr, template);
801 
802     // add params
803     const char * format = template->format;
804     uint16_t word;
805     uint32_t longword;
806     while (*format){
807         switch (*format++){
808             case '1':
809                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
810                 mesh_access_transport_add_uint8( transport_pdu, word);
811                 break;
812             case '2':
813                 word = va_arg(argptr, int);  // minimal va_arg is int: 2 bytes on 8+16 bit CPUs
814                 mesh_access_transport_add_uint16( transport_pdu, word);
815                 break;
816             case '3':
817                 longword = va_arg(argptr, uint32_t);
818                 mesh_access_transport_add_uint24( transport_pdu, longword);
819                 break;
820             case '4':
821                 longword = va_arg(argptr, uint32_t);
822                 mesh_access_transport_add_uint32( transport_pdu, longword);
823                 break;
824             case 'm':
825                 longword = va_arg(argptr, uint32_t);
826                 mesh_access_transport_add_model_identifier( transport_pdu, longword);
827                 break;
828             default:
829                 break;
830         }
831     }
832 
833     va_end(argptr);
834 
835     return transport_pdu;
836 }
837 
838 static const mesh_operation_t * mesh_model_lookup_operation_by_opcode(mesh_model_t * model, uint32_t opcode){
839     // find opcode in table
840     const mesh_operation_t * operation = model->operations;
841     if (operation == NULL) return NULL;
842     for ( ; operation->handler != NULL ; operation++){
843         if (operation->opcode != opcode) continue;
844         return operation;
845     }
846     return NULL;
847 }
848 
849 static const mesh_operation_t * mesh_model_lookup_operation(mesh_model_t * model, mesh_pdu_t * pdu){
850 
851     uint32_t opcode = 0;
852     uint16_t opcode_size = 0;
853     int ok = mesh_access_pdu_get_opcode( pdu, &opcode, &opcode_size);
854     if (!ok) return NULL;
855 
856     uint16_t len = mesh_pdu_len(pdu);
857 
858     // find opcode in table
859     const mesh_operation_t * operation = model->operations;
860     if (operation == NULL) return NULL;
861     for ( ; operation->handler != NULL ; operation++){
862         if (operation->opcode != opcode) continue;
863         if ((opcode_size + operation->minimum_length) > len) continue;
864         return operation;
865     }
866     return NULL;
867 }
868 
869 static int mesh_access_validate_appkey_index(mesh_model_t * model, uint16_t appkey_index){
870     // DeviceKey is valid for all models
871     if (appkey_index == MESH_DEVICE_KEY_INDEX) return 1;
872     // check if AppKey that is bound to this particular model
873     return mesh_model_contains_appkey(model, appkey_index);
874 }
875 
876 static void mesh_access_message_process_handler(mesh_pdu_t * pdu){
877     // get opcode and size
878     uint32_t opcode = 0;
879     uint16_t opcode_size = 0;
880 
881 
882     int ok = mesh_access_pdu_get_opcode( pdu, &opcode, &opcode_size);
883     if (!ok) {
884         mesh_access_message_processed(pdu);
885         return;
886     }
887 
888     uint16_t len = mesh_pdu_len(pdu);
889     printf("MESH Access Message, Opcode = %x: ", opcode);
890     switch (pdu->pdu_type){
891         case MESH_PDU_TYPE_NETWORK:
892             printf_hexdump(&((mesh_network_pdu_t *) pdu)->data[10], len);
893             break;
894         case MESH_PDU_TYPE_TRANSPORT:
895             printf_hexdump(((mesh_transport_pdu_t *) pdu)->data, len);
896             break;
897         default:
898             break;
899     }
900 
901     uint16_t src = mesh_pdu_src(pdu);
902     uint16_t dst = mesh_pdu_dst(pdu);
903     uint16_t appkey_index = mesh_pdu_appkey_index(pdu);
904     if (mesh_network_address_unicast(dst)){
905         // loookup element by unicast address
906         mesh_element_t * element = mesh_node_element_for_unicast_address(dst);
907         if (element != NULL){
908             // iterate over models, look for operation
909             mesh_model_iterator_t model_it;
910             mesh_model_iterator_init(&model_it, element);
911             while (mesh_model_iterator_has_next(&model_it)){
912                 mesh_model_t * model = mesh_model_iterator_next(&model_it);
913                 // find opcode in table
914                 const mesh_operation_t * operation = mesh_model_lookup_operation(model, pdu);
915                 if (operation == NULL) break;
916                 if (mesh_access_validate_appkey_index(model, appkey_index) == 0) break;
917                 mesh_access_acknowledged_received(src, opcode);
918                 operation->handler(model, pdu);
919                 return;
920             }
921         }
922     }
923     else if (mesh_network_address_group(dst)){
924 
925         // handle fixed group address
926         if (dst >= 0xff00){
927             int deliver_to_primary_element = 1;
928             switch (dst){
929                 case MESH_ADDRESS_ALL_PROXIES:
930                     if (mesh_foundation_gatt_proxy_get() == 1){
931                         deliver_to_primary_element = 1;
932                     }
933                     break;
934                 case MESH_ADDRESS_ALL_FRIENDS:
935                     // TODO: not implemented
936                     break;
937                 case MESH_ADDRESS_ALL_RELAYS:
938                     if (mesh_foundation_relay_get() == 1){
939                         deliver_to_primary_element =1;
940                     }
941                     break;
942                 case MESH_ADDRESS_ALL_NODES:
943                     deliver_to_primary_element = 1;
944                     break;
945                 default:
946                     break;
947             }
948             if (deliver_to_primary_element){
949                 mesh_model_iterator_t model_it;
950                 mesh_model_iterator_init(&model_it, mesh_node_get_primary_element());
951                 while (mesh_model_iterator_has_next(&model_it)){
952                     mesh_model_t * model = mesh_model_iterator_next(&model_it);
953                     // find opcode in table
954                     const mesh_operation_t * operation = mesh_model_lookup_operation(model, pdu);
955                     if (operation == NULL) continue;
956                     if (mesh_access_validate_appkey_index(model, appkey_index) == 0) continue;
957                     mesh_access_acknowledged_received(src, opcode);
958                     operation->handler(model, pdu);
959                     return;
960                 }
961             }
962         }
963         else {
964             // iterate over all elements / models, check subscription list
965             mesh_element_iterator_t it;
966             mesh_element_iterator_init(&it);
967             while (mesh_element_iterator_has_next(&it)){
968                 mesh_element_t * element = (mesh_element_t *) mesh_element_iterator_next(&it);
969                 mesh_model_iterator_t model_it;
970                 mesh_model_iterator_init(&model_it, element);
971                 while (mesh_model_iterator_has_next(&model_it)){
972                     mesh_model_t * model = mesh_model_iterator_next(&model_it);
973                     if (mesh_model_contains_subscription(model, dst)){
974                         // find opcode in table
975                         const mesh_operation_t * operation = mesh_model_lookup_operation(model, pdu);
976                         if (operation == NULL) continue;
977                         if (mesh_access_validate_appkey_index(model, appkey_index) == 0) continue;
978                         mesh_access_acknowledged_received(src, opcode);
979                         operation->handler(model, pdu);
980                         return;
981                     }
982                 }
983             }
984         }
985     }
986 
987     // operation not found -> done
988     printf("Message not handled\n");
989     mesh_access_message_processed(pdu);
990 }
991 
992 void mesh_access_message_processed(mesh_pdu_t * pdu){
993     mesh_upper_transport_message_processed_by_higher_layer(pdu);
994 }
995 
996 int mesh_model_contains_subscription(mesh_model_t * mesh_model, uint16_t address){
997     uint16_t i;
998     for (i=0;i<MAX_NR_MESH_SUBSCRIPTION_PER_MODEL;i++){
999         if (mesh_model->subscriptions[i] == address) return 1;
1000     }
1001     return 0;
1002 }
1003 
1004 static uint32_t mesh_network_key_tag_for_internal_index(uint16_t internal_index){
1005     return ((uint32_t) 'M' << 24) | ((uint32_t) 'N' << 16) | ((uint32_t) internal_index);
1006 }
1007 
1008 // Foundation state
1009 
1010 static const uint32_t mesh_foundation_state_tag = ((uint32_t) 'M' << 24) | ((uint32_t) 'F' << 16)  | ((uint32_t) 'N' << 8) | ((uint32_t) 'D' << 8);
1011 
1012 typedef struct {
1013     uint8_t gatt_proxy;
1014     uint8_t beacon;
1015     uint8_t default_ttl;
1016     uint8_t network_transmit;
1017     uint8_t relay;
1018     uint8_t relay_retransmit;
1019     uint8_t friend;
1020 } mesh_persistent_foundation_t;
1021 
1022 void mesh_foundation_state_load(void){
1023     mesh_access_setup_tlv();
1024     mesh_persistent_foundation_t data;
1025 
1026     int app_key_len = btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, mesh_foundation_state_tag, (uint8_t *) &data, sizeof(data));
1027     if (app_key_len == 0) return;
1028 
1029     mesh_foundation_gatt_proxy_set(data.gatt_proxy);
1030     mesh_foundation_beacon_set(data.gatt_proxy);
1031     mesh_foundation_default_ttl_set(data.default_ttl);
1032     mesh_foundation_friend_set(data.friend);
1033     mesh_foundation_network_transmit_set(data.network_transmit);
1034     mesh_foundation_relay_set(data.relay);
1035     mesh_foundation_relay_retransmit_set(data.relay_retransmit);
1036 }
1037 
1038 void mesh_foundation_state_store(void){
1039     mesh_access_setup_tlv();
1040     mesh_persistent_foundation_t data;
1041     data.gatt_proxy       = mesh_foundation_gatt_proxy_get();
1042     data.gatt_proxy       = mesh_foundation_beacon_get();
1043     data.default_ttl      = mesh_foundation_default_ttl_get();
1044     data.friend           = mesh_foundation_friend_get();
1045     data.network_transmit = mesh_foundation_network_transmit_get();
1046     data.relay            = mesh_foundation_relay_get();
1047     data.relay_retransmit = mesh_foundation_relay_retransmit_get();
1048     btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, mesh_foundation_state_tag, (uint8_t *) &data, sizeof(data));
1049 }
1050 
1051 // Mesh Network Keys
1052 typedef struct {
1053     uint16_t netkey_index;
1054 
1055     uint8_t  version;
1056 
1057     // net_key from provisioner or Config Model Client
1058     uint8_t net_key[16];
1059 
1060     // derived data
1061 
1062     // k1
1063     uint8_t identity_key[16];
1064     uint8_t beacon_key[16];
1065 
1066     // k3
1067     uint8_t network_id[8];
1068 
1069     // k2
1070     uint8_t nid;
1071     uint8_t encryption_key[16];
1072     uint8_t privacy_key[16];
1073 } mesh_persistent_net_key_t;
1074 
1075 void mesh_store_network_key(mesh_network_key_t * network_key){
1076     mesh_access_setup_tlv();
1077     mesh_persistent_net_key_t data;
1078     printf("Store NetKey: internal index 0x%x, NetKey Index 0x%06x, NID %02x: ", network_key->internal_index, network_key->netkey_index, network_key->nid);
1079     printf_hexdump(network_key->net_key, 16);
1080     uint32_t tag = mesh_network_key_tag_for_internal_index(network_key->internal_index);
1081     data.netkey_index = network_key->netkey_index;
1082     memcpy(data.net_key, network_key->net_key, 16);
1083     memcpy(data.identity_key, network_key->identity_key, 16);
1084     memcpy(data.beacon_key, network_key->beacon_key, 16);
1085     memcpy(data.network_id, network_key->network_id, 8);
1086     data.nid = network_key->nid;
1087     data.version = network_key->version;
1088     memcpy(data.encryption_key, network_key->encryption_key, 16);
1089     memcpy(data.privacy_key, network_key->privacy_key, 16);
1090     btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(mesh_persistent_net_key_t));
1091 }
1092 
1093 void mesh_delete_network_key(uint16_t internal_index){
1094     mesh_access_setup_tlv();
1095     uint32_t tag = mesh_network_key_tag_for_internal_index(internal_index);
1096     btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, tag);
1097 }
1098 
1099 
1100 void mesh_load_network_keys(void){
1101     mesh_access_setup_tlv();
1102     printf("Load Network Keys\n");
1103     uint16_t internal_index;
1104     for (internal_index = 0; internal_index < MAX_NR_MESH_NETWORK_KEYS; internal_index++){
1105         mesh_persistent_net_key_t data;
1106         uint32_t tag = mesh_network_key_tag_for_internal_index(internal_index);
1107         int netkey_len = btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data));
1108         if (netkey_len != sizeof(mesh_persistent_net_key_t)) continue;
1109 
1110         mesh_network_key_t * network_key = btstack_memory_mesh_network_key_get();
1111         if (network_key == NULL) return;
1112 
1113         network_key->netkey_index = data.netkey_index;
1114         memcpy(network_key->net_key, data.net_key, 16);
1115         memcpy(network_key->identity_key, data.identity_key, 16);
1116         memcpy(network_key->beacon_key, data.beacon_key, 16);
1117         memcpy(network_key->network_id, data.network_id, 8);
1118         network_key->nid = data.nid;
1119         network_key->version = data.version;
1120         memcpy(network_key->encryption_key, data.encryption_key, 16);
1121         memcpy(network_key->privacy_key, data.privacy_key, 16);
1122 
1123 #ifdef ENABLE_GATT_BEARER
1124         // setup advertisement with network id
1125         network_key->advertisement_with_network_id.adv_length = mesh_proxy_setup_advertising_with_network_id(network_key->advertisement_with_network_id.adv_data, network_key->network_id);
1126 #endif
1127 
1128         mesh_network_key_add(network_key);
1129 
1130         mesh_subnet_setup_for_netkey_index(network_key->netkey_index);
1131 
1132         printf("- internal index 0x%x, NetKey Index 0x%06x, NID %02x: ", network_key->internal_index, network_key->netkey_index, network_key->nid);
1133         printf_hexdump(network_key->net_key, 16);
1134     }
1135 }
1136 
1137 void mesh_delete_network_keys(void){
1138     printf("Delete Network Keys\n");
1139 
1140     uint16_t internal_index;
1141     for (internal_index = 0; internal_index < MAX_NR_MESH_NETWORK_KEYS; internal_index++){
1142         mesh_delete_network_key(internal_index);
1143     }
1144 }
1145 
1146 
1147 // Mesh App Keys
1148 
1149 typedef struct {
1150     uint16_t netkey_index;
1151     uint16_t appkey_index;
1152     uint8_t  aid;
1153     uint8_t  version;
1154     uint8_t  key[16];
1155 } mesh_persistent_app_key_t;
1156 
1157 static uint32_t mesh_transport_key_tag_for_internal_index(uint16_t internal_index){
1158     return ((uint32_t) 'M' << 24) | ((uint32_t) 'A' << 16) | ((uint32_t) internal_index);
1159 }
1160 
1161 void mesh_store_app_key(mesh_transport_key_t * app_key){
1162     mesh_access_setup_tlv();
1163 
1164     mesh_persistent_app_key_t data;
1165     printf("Store AppKey: internal index 0x%x, AppKey Index 0x%06x, AID %02x: ", app_key->internal_index, app_key->appkey_index, app_key->aid);
1166     printf_hexdump(app_key->key, 16);
1167     uint32_t tag = mesh_transport_key_tag_for_internal_index(app_key->internal_index);
1168     data.netkey_index = app_key->netkey_index;
1169     data.appkey_index = app_key->appkey_index;
1170     data.aid = app_key->aid;
1171     data.version = app_key->version;
1172     memcpy(data.key, app_key->key, 16);
1173     btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data));
1174 }
1175 
1176 void mesh_delete_app_key(uint16_t internal_index){
1177     mesh_access_setup_tlv();
1178 
1179     uint32_t tag = mesh_transport_key_tag_for_internal_index(internal_index);
1180     btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, tag);
1181 }
1182 
1183 void mesh_load_app_keys(void){
1184     mesh_access_setup_tlv();
1185     printf("Load App Keys\n");
1186     uint16_t internal_index;
1187     for (internal_index = 0; internal_index < MAX_NR_MESH_TRANSPORT_KEYS; internal_index++){
1188         mesh_persistent_app_key_t data;
1189         uint32_t tag = mesh_transport_key_tag_for_internal_index(internal_index);
1190         int app_key_len = btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data));
1191         if (app_key_len == 0) continue;
1192 
1193         mesh_transport_key_t * key = btstack_memory_mesh_transport_key_get();
1194         if (key == NULL) return;
1195 
1196         key->internal_index = internal_index;
1197         key->appkey_index = data.appkey_index;
1198         key->netkey_index = data.netkey_index;
1199         key->aid          = data.aid;
1200         key->akf          = 1;
1201         key->version      = data.version;
1202         memcpy(key->key, data.key, 16);
1203         mesh_transport_key_add(key);
1204         printf("- internal index 0x%x, AppKey Index 0x%06x, AID %02x: ", key->internal_index, key->appkey_index, key->aid);
1205         printf_hexdump(key->key, 16);
1206     }
1207 }
1208 
1209 void mesh_delete_app_keys(void){
1210     printf("Delete App Keys\n");
1211 
1212     uint16_t internal_index;
1213     for (internal_index = 0; internal_index < MAX_NR_MESH_TRANSPORT_KEYS; internal_index++){
1214         mesh_delete_app_key(internal_index);
1215     }
1216 }
1217 
1218 
1219 // Model to Appkey List
1220 
1221 static uint32_t mesh_model_tag_for_index(uint16_t internal_model_id){
1222     return ((uint32_t) 'M' << 24) | ((uint32_t) 'B' << 16) | ((uint32_t) internal_model_id);
1223 }
1224 
1225 static void mesh_load_appkey_list(mesh_model_t * model){
1226     mesh_access_setup_tlv();
1227     uint32_t tag = mesh_model_tag_for_index(model->mid);
1228     btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &model->appkey_indices, sizeof(model->appkey_indices));
1229 }
1230 
1231 static void mesh_store_appkey_list(mesh_model_t * model){
1232     mesh_access_setup_tlv();
1233     uint32_t tag = mesh_model_tag_for_index(model->mid);
1234     btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &model->appkey_indices, sizeof(model->appkey_indices));
1235 }
1236 
1237 static void mesh_delete_appkey_list(mesh_model_t * model){
1238     mesh_access_setup_tlv();
1239     uint32_t tag = mesh_model_tag_for_index(model->mid);
1240     btstack_tlv_singleton_impl->delete_tag(btstack_tlv_singleton_context, tag);
1241 }
1242 
1243 void mesh_load_appkey_lists(void){
1244     printf("Load Appkey Lists\n");
1245     // iterate over elements and models
1246     mesh_element_iterator_t element_it;
1247     mesh_element_iterator_init(&element_it);
1248     while (mesh_element_iterator_has_next(&element_it)){
1249         mesh_element_t * element = mesh_element_iterator_next(&element_it);
1250         mesh_model_iterator_t model_it;
1251         mesh_model_iterator_init(&model_it, element);
1252         while (mesh_model_iterator_has_next(&model_it)){
1253             mesh_model_t * model = mesh_model_iterator_next(&model_it);
1254             mesh_load_appkey_list(model);
1255         }
1256     }
1257 }
1258 
1259 void mesh_delete_appkey_lists(void){
1260     printf("Delete Appkey Lists\n");
1261     mesh_access_setup_tlv();
1262     // iterate over elements and models
1263     mesh_element_iterator_t element_it;
1264     mesh_element_iterator_init(&element_it);
1265     while (mesh_element_iterator_has_next(&element_it)){
1266         mesh_element_t * element = mesh_element_iterator_next(&element_it);
1267         mesh_model_iterator_t model_it;
1268         mesh_model_iterator_init(&model_it, element);
1269         while (mesh_model_iterator_has_next(&model_it)){
1270             mesh_model_t * model = mesh_model_iterator_next(&model_it);
1271             mesh_delete_appkey_list(model);
1272         }
1273     }
1274 }
1275 
1276 void mesh_model_reset_appkeys(mesh_model_t * mesh_model){
1277     uint16_t i;
1278     for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){
1279         mesh_model->appkey_indices[i] = MESH_APPKEY_INVALID;
1280     }
1281 }
1282 
1283 uint8_t mesh_model_bind_appkey(mesh_model_t * mesh_model, uint16_t appkey_index){
1284     uint16_t i;
1285     for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){
1286         if (mesh_model->appkey_indices[i] == appkey_index) return MESH_FOUNDATION_STATUS_SUCCESS;
1287     }
1288     for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){
1289         if (mesh_model->appkey_indices[i] == MESH_APPKEY_INVALID) {
1290             mesh_model->appkey_indices[i] = appkey_index;
1291             mesh_store_appkey_list(mesh_model);
1292             return MESH_FOUNDATION_STATUS_SUCCESS;
1293         }
1294     }
1295     return MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES;
1296 }
1297 
1298 void mesh_model_unbind_appkey(mesh_model_t * mesh_model, uint16_t appkey_index){
1299     uint16_t i;
1300     for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){
1301         if (mesh_model->appkey_indices[i] == appkey_index) {
1302             mesh_model->appkey_indices[i] = MESH_APPKEY_INVALID;
1303             mesh_store_appkey_list(mesh_model);
1304         }
1305     }
1306 }
1307 
1308 int mesh_model_contains_appkey(mesh_model_t * mesh_model, uint16_t appkey_index){
1309     uint16_t i;
1310     for (i=0;i<MAX_NR_MESH_APPKEYS_PER_MODEL;i++){
1311         if (mesh_model->appkey_indices[i] == appkey_index) return 1;
1312     }
1313     return 0;
1314 
1315 }
1316 
1317 // Mesh IV Index
1318 static uint32_t mesh_tag_for_iv_index_and_seq_number(void){
1319     return ((uint32_t) 'M' << 24) | ((uint32_t) 'F' << 16) | ((uint32_t) 'I' << 9) | ((uint32_t) 'S');
1320 }
1321 
1322 typedef struct {
1323     uint32_t iv_index;
1324     uint32_t seq_number;
1325 } iv_index_and_sequence_number_t;
1326 
1327 static uint32_t sequence_number_last_stored;
1328 static uint32_t sequence_number_storage_trigger;
1329 
1330 #define MESH_SEQUENCE_NUMBER_STORAGE_INTERVAL 1000
1331 
1332 void mesh_store_iv_index_after_provisioning(uint32_t iv_index){
1333     iv_index_and_sequence_number_t data;
1334     mesh_access_setup_tlv();
1335     uint32_t tag = mesh_tag_for_iv_index_and_seq_number();
1336     data.iv_index   = iv_index;
1337     data.seq_number = 0;
1338     btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data));
1339 
1340     sequence_number_last_stored = data.seq_number;
1341     sequence_number_storage_trigger = sequence_number_last_stored + MESH_SEQUENCE_NUMBER_STORAGE_INTERVAL;
1342 }
1343 
1344 void mesh_store_iv_index_and_sequence_number(void){
1345     iv_index_and_sequence_number_t data;
1346     mesh_access_setup_tlv();
1347     uint32_t tag = mesh_tag_for_iv_index_and_seq_number();
1348     data.iv_index   = mesh_get_iv_index();
1349     data.seq_number = mesh_sequence_number_peek();
1350     btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data));
1351 
1352     sequence_number_last_stored = data.seq_number;
1353     sequence_number_storage_trigger = sequence_number_last_stored + MESH_SEQUENCE_NUMBER_STORAGE_INTERVAL;
1354 }
1355 
1356 static void mesh_load_iv_index_and_sequence_number(void){
1357     iv_index_and_sequence_number_t data;
1358     mesh_access_setup_tlv();
1359     uint32_t tag = mesh_tag_for_iv_index_and_seq_number();
1360     btstack_tlv_singleton_impl->get_tag(btstack_tlv_singleton_context, tag, (uint8_t *) &data, sizeof(data));
1361     mesh_set_iv_index(data.iv_index);
1362     mesh_sequence_number_set(data.seq_number);
1363 }
1364 
1365 void mesh_restore_iv_index_and_sequence_number(void){
1366     mesh_load_iv_index_and_sequence_number();
1367 
1368     // bump sequence number to account for only interval storage
1369     uint32_t seq_number = mesh_sequence_number_peek();
1370     seq_number += MESH_SEQUENCE_NUMBER_STORAGE_INTERVAL;
1371     mesh_sequence_number_set(seq_number);
1372 
1373     mesh_store_iv_index_and_sequence_number();
1374 }
1375 
1376 // higher layer
1377 static void mesh_persist_iv_index_and_sequence_number(void){
1378     if (mesh_sequence_number_peek() >= sequence_number_storage_trigger){
1379         mesh_store_iv_index_and_sequence_number();
1380     }
1381 }
1382 
1383 
1384 // Mesh Model Publication
1385 static btstack_timer_source_t mesh_access_publication_timer;
1386 
1387 static uint32_t mesh_model_publication_retransmit_count(uint8_t retransmit){
1388     return retransmit & 0x07u;
1389 }
1390 
1391 static uint32_t mesh_model_publication_retransmission_period_ms(uint8_t retransmit){
1392     return ((uint32_t)((retransmit >> 3) + 1)) * 50;
1393 }
1394 
1395 static void mesh_model_publication_setup_publication(mesh_publication_model_t * publication_model, uint32_t now){
1396 
1397     // set retransmit counter
1398     publication_model->retransmit_count = mesh_model_publication_retransmit_count(publication_model->retransmit);
1399 
1400     // schedule next publication or retransmission
1401     uint32_t publication_period_ms = mesh_access_transitions_step_ms_from_gdtt(publication_model->period);
1402 
1403     // set next publication
1404     if (publication_period_ms != 0){
1405         publication_model->next_publication_ms = now + publication_period_ms;
1406         publication_model->state = MESH_MODEL_PUBLICATION_STATE_W4_PUBLICATION_MS;
1407     }
1408 }
1409 
1410 static void mesh_model_publication_setup_retransmission(mesh_publication_model_t * publication_model, uint32_t now){
1411     uint8_t num_retransmits = mesh_model_publication_retransmit_count(publication_model->retransmit);
1412     if (num_retransmits == 0) return;
1413 
1414     // calc next retransmit time
1415     uint32_t retransmission_ms = now + mesh_model_publication_retransmission_period_ms(publication_model->retransmit);
1416 
1417     // ignore if retransmission would be after next publication timeout
1418     if (publication_model->state == MESH_MODEL_PUBLICATION_STATE_W4_PUBLICATION_MS){
1419         if (btstack_time_delta(retransmission_ms, publication_model->next_publication_ms) > 0) return;
1420     }
1421 
1422     // schedule next retransmission
1423     publication_model->next_retransmit_ms = retransmission_ms;
1424     publication_model->state = MESH_MODEL_PUBLICATION_STATE_W4_RETRANSMIT_MS;
1425 }
1426 
1427 static void mesh_model_publication_publish_now_model(mesh_model_t * mesh_model){
1428     mesh_publication_model_t * publication_model = mesh_model->publication_model;
1429     if (publication_model == NULL) return;
1430     if (publication_model->publish_state_fn == NULL) return;
1431     uint16_t dest = publication_model->address;
1432     if (dest == MESH_ADDRESS_UNSASSIGNED) return;
1433     uint16_t appkey_index = publication_model->appkey_index;
1434     mesh_transport_key_t * app_key = mesh_transport_key_get(appkey_index);
1435     if (app_key == NULL) return;
1436 
1437     // compose message
1438     mesh_pdu_t * pdu = (*publication_model->publish_state_fn)(mesh_model);
1439     if (pdu == NULL) return;
1440 
1441     mesh_upper_transport_setup_access_pdu_header(pdu, app_key->netkey_index, appkey_index, publication_model->ttl, mesh_access_get_element_address(mesh_model), dest, 0);
1442     mesh_upper_transport_send_access_pdu(pdu);
1443 }
1444 
1445 static void mesh_model_publication_run(btstack_timer_source_t * ts){
1446     UNUSED(ts);
1447 
1448     uint32_t now = btstack_run_loop_get_time_ms();
1449 
1450     // iterate over elements and models and handle time-based transitions
1451     mesh_element_iterator_t element_it;
1452     mesh_element_iterator_init(&element_it);
1453     while (mesh_element_iterator_has_next(&element_it)){
1454         mesh_element_t * element = mesh_element_iterator_next(&element_it);
1455         mesh_model_iterator_t model_it;
1456         mesh_model_iterator_init(&model_it, element);
1457         while (mesh_model_iterator_has_next(&model_it)){
1458             mesh_model_t * mesh_model = mesh_model_iterator_next(&model_it);
1459             mesh_publication_model_t * publication_model = mesh_model->publication_model;
1460             if (publication_model == NULL) continue;
1461 
1462             // schedule next
1463             switch (publication_model->state){
1464                 case MESH_MODEL_PUBLICATION_STATE_W4_PUBLICATION_MS:
1465                     if (btstack_time_delta(publication_model->next_publication_ms, now) > 0) break;
1466                     // timeout
1467                     publication_model->publish_now = 1;
1468                     // schedule next publication and retransmission
1469                     mesh_model_publication_setup_publication(publication_model, now);
1470                     mesh_model_publication_setup_retransmission(publication_model, now);
1471                     break;
1472                 case MESH_MODEL_PUBLICATION_STATE_W4_RETRANSMIT_MS:
1473                     if (btstack_time_delta(publication_model->next_retransmit_ms, now) > 0) break;
1474                     // timeout
1475                     publication_model->publish_now = 1;
1476                     publication_model->retransmit_count--;
1477                     // schedule next retransmission
1478                     mesh_model_publication_setup_retransmission(publication_model, now);
1479                     break;
1480                 default:
1481                     break;
1482             }
1483 
1484             if (publication_model->publish_now == 0) continue;
1485 
1486             publication_model->publish_now = 0;
1487             mesh_model_publication_publish_now_model(mesh_model);
1488         }
1489     }
1490 
1491     int32_t next_timeout_ms = 0;
1492     mesh_element_iterator_init(&element_it);
1493     while (mesh_element_iterator_has_next(&element_it)){
1494         mesh_element_t * element = mesh_element_iterator_next(&element_it);
1495         mesh_model_iterator_t model_it;
1496         mesh_model_iterator_init(&model_it, element);
1497         while (mesh_model_iterator_has_next(&model_it)){
1498             mesh_model_t * mesh_model = mesh_model_iterator_next(&model_it);
1499             mesh_publication_model_t * publication_model = mesh_model->publication_model;
1500             if (publication_model == NULL) continue;
1501 
1502             // schedule next
1503             int32_t timeout_delta_ms;
1504             switch (publication_model->state){
1505                 case MESH_MODEL_PUBLICATION_STATE_W4_PUBLICATION_MS:
1506                     timeout_delta_ms = btstack_time_delta(publication_model->next_publication_ms, now);
1507                     if (next_timeout_ms == 0 || timeout_delta_ms < next_timeout_ms){
1508                         next_timeout_ms = timeout_delta_ms;
1509                     }
1510                     break;
1511                 case MESH_MODEL_PUBLICATION_STATE_W4_RETRANSMIT_MS:
1512                     timeout_delta_ms = btstack_time_delta(publication_model->next_retransmit_ms, now);
1513                     if (next_timeout_ms == 0 || timeout_delta_ms < next_timeout_ms){
1514                         next_timeout_ms = timeout_delta_ms;
1515                     }
1516                     break;
1517                 default:
1518                     break;
1519             }
1520         }
1521     }
1522 
1523     // set timer
1524     if (next_timeout_ms == 0) return;
1525 
1526     btstack_run_loop_set_timer(&mesh_access_publication_timer, next_timeout_ms);
1527     btstack_run_loop_set_timer_handler(&mesh_access_publication_timer, mesh_model_publication_run);
1528     btstack_run_loop_add_timer(&mesh_access_publication_timer);
1529 }
1530 
1531 void mesh_model_publication_start(mesh_model_t * mesh_model){
1532     mesh_publication_model_t * publication_model = mesh_model->publication_model;
1533     if (publication_model == NULL) return;
1534 
1535     // reset state
1536     publication_model->state = MESH_MODEL_PUBLICATION_STATE_IDLE;
1537 
1538     // publish right away
1539     publication_model->publish_now = 1;
1540 
1541     // setup next publication and retransmission
1542     uint32_t now = btstack_run_loop_get_time_ms();
1543     mesh_model_publication_setup_publication(publication_model, now);
1544     mesh_model_publication_setup_retransmission(publication_model, now);
1545 
1546     mesh_model_publication_run(NULL);
1547 }
1548 
1549 void mesh_model_publication_stop(mesh_model_t * mesh_model){
1550     mesh_publication_model_t * publication_model = mesh_model->publication_model;
1551     if (publication_model == NULL) return;
1552 
1553     // reset state
1554     publication_model->state = MESH_MODEL_PUBLICATION_STATE_IDLE;
1555 }
1556 
1557 void mesh_access_state_changed(mesh_model_t * mesh_model){
1558     mesh_publication_model_t * publication_model = mesh_model->publication_model;
1559     if (publication_model == NULL) return;
1560     publication_model->publish_now = 1;
1561     mesh_model_publication_run(NULL);
1562 }
1563 
1564 void mesh_access_netkey_finalize(mesh_network_key_t * network_key){
1565     mesh_network_key_remove(network_key);
1566     mesh_delete_network_key(network_key->internal_index);
1567     btstack_memory_mesh_network_key_free(network_key);
1568 }
1569 
1570 void mesh_access_appkey_finalize(mesh_transport_key_t * transport_key){
1571     mesh_transport_key_remove(transport_key);
1572     mesh_delete_app_key(transport_key->appkey_index);
1573     btstack_memory_mesh_transport_key_free(transport_key);
1574 }
1575 
1576 void mesh_access_key_refresh_revoke_keys(mesh_subnet_t * subnet){
1577     // delete old netkey index
1578     mesh_access_netkey_finalize(subnet->old_key);
1579     subnet->old_key = subnet->new_key;
1580     subnet->new_key = NULL;
1581 
1582     // delete old appkeys, if any
1583     mesh_transport_key_iterator_t it;
1584     mesh_transport_key_iterator_init(&it, subnet->netkey_index);
1585     while (mesh_transport_key_iterator_has_more(&it)){
1586         mesh_transport_key_t * transport_key = mesh_transport_key_iterator_get_next(&it);
1587         if (transport_key->old_key == 0) continue;
1588         mesh_access_appkey_finalize(transport_key);
1589     }
1590 }
1591 
1592 static void mesh_access_secure_network_beacon_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){
1593     UNUSED(channel);
1594     UNUSED(size);
1595 
1596     if (packet_type != MESH_BEACON_PACKET) return;
1597 
1598     // lookup subnet and netkey by network id
1599     uint8_t * beacon_network_id = &packet[2];
1600     mesh_subnet_iterator_t it;
1601     mesh_subnet_iterator_init(&it);
1602     mesh_subnet_t * subnet = NULL;
1603     mesh_network_key_t * network_key = NULL;
1604     uint8_t new_key = 0;
1605     while (mesh_subnet_iterator_has_more(&it)){
1606         mesh_subnet_t * item = mesh_subnet_iterator_get_next(&it);
1607         if (memcmp(item->old_key->network_id, beacon_network_id, 8) == 0 ) {
1608             subnet = item;
1609             network_key = item->old_key;
1610         }
1611         if (item->new_key != NULL && memcmp(item->new_key->network_id, beacon_network_id, 8) == 0 ) {
1612             subnet = item;
1613             network_key = item->new_key;
1614             new_key = 1;
1615         }
1616         break;
1617     }
1618     if (subnet == NULL) return;
1619 
1620     uint8_t flags = packet[1];
1621 
1622     // Key refresh via secure network beacons that are authenticated with new netkey
1623     if (new_key){
1624         // either first or second phase (in phase 0, new key is not set)
1625         int key_refresh_flag = flags & 1;
1626         if (key_refresh_flag){
1627             //  transition to phase 3 from either phase 1 or 2
1628             switch (subnet->key_refresh){
1629                 case MESH_KEY_REFRESH_FIRST_PHASE:
1630                 case MESH_KEY_REFRESH_SECOND_PHASE:
1631                     mesh_access_key_refresh_revoke_keys(subnet);
1632                     subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE;
1633                     break;
1634                 default:
1635                     break;
1636             }
1637         } else {
1638             //  transition to phase 2 from either phase 1
1639             switch (subnet->key_refresh){
1640                 case MESH_KEY_REFRESH_FIRST_PHASE:
1641                     // -- update state
1642                     subnet->key_refresh = MESH_KEY_REFRESH_SECOND_PHASE;
1643                     break;
1644                 default:
1645                     break;
1646             }
1647         }
1648     }
1649 
1650     // IV Update
1651 
1652     int     beacon_iv_update_active = flags & 2;
1653     int     local_iv_update_active = mesh_iv_update_active();
1654     uint32_t beacon_iv_index = big_endian_read_32(packet, 10);
1655     uint32_t local_iv_index = mesh_get_iv_index();
1656 
1657     int32_t iv_index_delta = (int32_t)(beacon_iv_index - local_iv_index);
1658 
1659     // "If a node in Normal Operation receives a Secure Network beacon with an IV index less than the last known IV Index or greater than
1660     //  the last known IV Index + 42, the Secure Network beacon shall be ignored."
1661     if (iv_index_delta < 0 || iv_index_delta > 42){
1662         return;
1663     }
1664 
1665     // "If a node in Normal Operation receives a Secure Network beacon with an IV index equal to the last known IV index+1 and
1666     //  the IV Update Flag set to 0, the node may update its IV without going to the IV Update in Progress state, or it may initiate
1667     //  an IV Index Recovery procedure (Section 3.10.6), or it may ignore the Secure Network beacon. The node makes the choice depending
1668     //  on the time since last IV update and the likelihood that the node has missed the Secure Network beacons with the IV update Flag set to 1.""
1669     if (local_iv_update_active == 0 && beacon_iv_update_active == 0 && iv_index_delta == 1){
1670         // instant iv update
1671         mesh_set_iv_index( beacon_iv_index );
1672         // store updated iv index
1673         mesh_store_iv_index_and_sequence_number();
1674         return;
1675     }
1676 
1677     // "If this node is a member of a primary subnet and receives a Secure Network beacon on a secondary subnet with an IV Index greater than
1678     //  the last known IV Index of the primary subnet, the Secure Network beacon shall be ignored."
1679     int member_of_primary_subnet = mesh_subnet_get_by_netkey_index(0) != NULL;
1680     int beacon_on_secondary_subnet = subnet->netkey_index != 0;
1681     if (member_of_primary_subnet && beacon_on_secondary_subnet && iv_index_delta > 0){
1682         return;
1683     }
1684 
1685     // "If a node in Normal Operation receives a Secure Network beacon with an IV index greater than the last known IV Index + 1..."
1686     // "... it may initiate an IV Index Recovery procedure, see Section 3.10.6."
1687     if (local_iv_update_active == 0 && iv_index_delta > 1){
1688         // "Upon receiving and successfully authenticating a Secure Network beacon for a primary subnet... "
1689         int beacon_on_primary_subnet = subnet->netkey_index == 0;
1690         if (!beacon_on_primary_subnet) return;
1691         // "... whose IV Index is 1 or more higher than the current known IV Index, the node shall "
1692         // " set its current IV Index and its current IV Update procedure state from the values in this Secure Network beacon."
1693         mesh_iv_index_recovered(beacon_iv_update_active, beacon_iv_index);
1694         // store updated iv index if in normal mode
1695         if (beacon_iv_update_active == 0){
1696             mesh_store_iv_index_and_sequence_number();
1697         }
1698         return;
1699     }
1700 
1701     if (local_iv_update_active == 0){
1702         if (beacon_iv_update_active){
1703             mesh_trigger_iv_update();
1704         }
1705     } else {
1706         if (beacon_iv_update_active == 0){
1707             // " At the point of transition, the node shall reset the sequence number to 0x000000."
1708             mesh_sequence_number_set(0);
1709             mesh_iv_update_completed();
1710             // store updated iv index
1711             mesh_store_iv_index_and_sequence_number();
1712         }
1713     }
1714 }
1715 
1716 void mesh_access_setup_from_provisioning_data(const mesh_provisioning_data_t * provisioning_data){
1717 
1718     // set iv_index and iv index update active
1719     int iv_index_update_active = (provisioning_data->flags & 2) >> 1;
1720     mesh_iv_index_recovered(iv_index_update_active, provisioning_data->iv_index);
1721 
1722     // set unicast address
1723     mesh_node_primary_element_address_set(provisioning_data->unicast_address);
1724 
1725     // set device_key
1726     mesh_transport_set_device_key(provisioning_data->device_key);
1727 
1728     if (provisioning_data->network_key){
1729 
1730         // setup primary network with provisioned netkey
1731         mesh_network_key_add(provisioning_data->network_key);
1732 
1733         // setup primary network
1734         mesh_subnet_setup_for_netkey_index(provisioning_data->network_key->netkey_index);
1735 
1736         // start sending Secure Network Beacons
1737         mesh_subnet_t * provisioned_subnet = mesh_subnet_get_by_netkey_index(provisioning_data->network_key->netkey_index);
1738         beacon_secure_network_start(provisioned_subnet);
1739     }
1740 
1741     // Mesh Proxy
1742 #ifdef ENABLE_MESH_PROXY_SERVER
1743     // Setup Proxy
1744     mesh_proxy_init(provisioning_data->unicast_address);
1745     mesh_proxy_start_advertising_with_network_id();
1746 #endif
1747 }
1748 
1749 static btstack_crypto_random_t mesh_access_crypto_random;
1750 
1751 static uint8_t random_device_uuid[16];
1752 
1753 static void mesh_access_setup_unprovisioned_device(void * arg){
1754     // set random value
1755     if (arg == NULL){
1756         mesh_node_set_device_uuid(random_device_uuid);
1757     }
1758 
1759 #ifdef ENABLE_MESH_PB_ADV
1760     // PB-ADV
1761     beacon_unprovisioned_device_start(mesh_node_get_device_uuid(), 0);
1762 #endif
1763 #ifdef ENABLE_MESH_PB_GATT
1764     mesh_proxy_start_advertising_unprovisioned_device();
1765 #endif
1766 }
1767 
1768 void mesh_access_setup_without_provisiong_data(void){
1769     const uint8_t * device_uuid = mesh_node_get_device_uuid();
1770     if (device_uuid){
1771         mesh_access_setup_unprovisioned_device((void *)device_uuid);
1772     } else{
1773         btstack_crypto_random_generate(&mesh_access_crypto_random, random_device_uuid, 16, &mesh_access_setup_unprovisioned_device, NULL);
1774     }
1775 }
1776 
1777