mesh: transport ignore segments for older messages

This commit is contained in:
Matthias Ringwald 2019-01-28 21:03:26 +01:00
parent ddd27aa129
commit fd803dcccd

View File

@ -197,6 +197,7 @@ static uint8_t mesh_network_send(uint16_t netkey_index, uint8_t ctl, uint8_t ttl
#define MESH_ADDRESS_UNSASSIGNED 0xfffb
static uint16_t mesh_seq_auth_single_src = MESH_ADDRESS_UNSASSIGNED;
static uint32_t mesh_seq_auth_single_seq;
static uint16_t mesh_seq_auth_single_zero;
void mesh_seq_auth_reset(void){
mesh_seq_auth_single_src = MESH_ADDRESS_UNSASSIGNED;
@ -218,6 +219,20 @@ static int mesh_seq_auth_validate(uint16_t src, uint32_t seq){
return 0;
}
static int mesh_seq_zero_validate(uint16_t src, uint16_t seq_zero){
// assume mesh_seq_auth_validate was already called
if (mesh_seq_auth_single_src == MESH_ADDRESS_UNSASSIGNED) return 0;
if (mesh_seq_auth_single_src != src){
return 1;
}
if (mesh_seq_auth_single_zero >= seq_zero){
return 2;
}
mesh_seq_auth_single_zero = seq_zero;
return 0;
}
// stub lower transport
static void mesh_lower_transport_run(void);
@ -722,20 +737,36 @@ static void mesh_transport_abort_transmission(void){
}
static mesh_transport_pdu_t * mesh_transport_pdu_for_segmented_message(mesh_network_pdu_t * network_pdu){
// uint16_t src = mesh_network_src(next_pdu);
if (test_transport_pdu == NULL){
test_transport_pdu = btstack_memory_mesh_transport_pdu_get();
// copy meta data
memcpy(test_transport_pdu->network_header, network_pdu->data, 9);
test_transport_pdu->netkey_index = network_pdu->netkey_index;
test_transport_pdu->block_ack = 0;
test_transport_pdu->acknowledgement_timer_active = 0;
printf("mesh_transport_pdu_for_segmented_message: setup transport pdu %p for src %x\n", test_transport_pdu, mesh_transport_src(test_transport_pdu));
// tracks last received seq auth and indirectly drops segments for older transport pdus
uint16_t seq_zero = ( big_endian_read_16(mesh_network_pdu_data(network_pdu), 1) >> 2) & 0x1fff;
if (test_transport_pdu){
uint32_t seq = mesh_transport_seq(test_transport_pdu);
// check if segment for same seq zero
if (seq == seq_zero) {
printf("mesh_transport_pdu_for_segmented_message: segment for current transport pdu with seq %x\n", seq);
return test_transport_pdu;
} else {
// seq zero differs from current transport pdu
printf("mesh_transport_pdu_for_segmented_message: drop segment. current transport pdu seq %x, now %x\n", seq, seq_zero);
return NULL;
}
} else {
printf("mesh_transport_pdu_for_segmented_message: transport pdu %p already set up for src %x\n", test_transport_pdu, mesh_transport_src(test_transport_pdu));
// no transport pdu acive, check if seq zero is new
if (mesh_seq_zero_validate(mesh_network_src(network_pdu), seq_zero) == 0){
test_transport_pdu = btstack_memory_mesh_transport_pdu_get();
// copy meta data
memcpy(test_transport_pdu->network_header, network_pdu->data, 9);
test_transport_pdu->netkey_index = network_pdu->netkey_index;
test_transport_pdu->block_ack = 0;
test_transport_pdu->acknowledgement_timer_active = 0;
printf("mesh_transport_pdu_for_segmented_message: setup transport pdu %p for src %x, seq %06x\n", test_transport_pdu, mesh_transport_src(test_transport_pdu), mesh_transport_seq(test_transport_pdu));
return test_transport_pdu;
} else {
// seq zero differs from current transport pdu
printf("mesh_transport_pdu_for_segmented_message: drop segment for old seq %x\n", seq_zero);
return NULL;
}
}
// TODO validate SeqZero, reset buffer if needed
return test_transport_pdu;
}
static void mesh_lower_transport_process_segment( mesh_transport_pdu_t * transport_pdu, mesh_network_pdu_t * network_pdu){