mirror of
https://github.com/CovidBraceletPrj/CovidBracelet.git
synced 2024-12-05 00:55:43 +01:00
Add records api, move sequence numbers into own file, adjust storage api
This commit is contained in:
parent
0a5323674a
commit
b98eea970c
@ -45,7 +45,7 @@ typedef struct contact {
|
||||
uint32_t most_recent_contact_time; //TODO: what is the correct type here?
|
||||
uint32_t first_contact_time; //TODO: what is the correct type here?
|
||||
uint16_t cnt;
|
||||
int8_t max_rssi;
|
||||
rssi_t max_rssi;
|
||||
rolling_proximity_identifier_t rolling_proximity_identifier;
|
||||
associated_encrypted_metadata_t associated_encrypted_metadata;
|
||||
} contact_t;
|
||||
|
@ -28,4 +28,6 @@ typedef struct associated_encrypted_metadata {
|
||||
uint8_t data[sizeof(bt_metadata_t)];
|
||||
} __packed associated_encrypted_metadata_t;
|
||||
|
||||
typedef uint8_t rssi_t;
|
||||
|
||||
#endif
|
||||
|
74
src/records.c
Normal file
74
src/records.c
Normal file
@ -0,0 +1,74 @@
|
||||
#include <string.h>
|
||||
#include "records.h"
|
||||
#include "covid_types.h"
|
||||
|
||||
|
||||
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
||||
record_sequence_number_t* opt_start,
|
||||
record_sequence_number_t* opt_end) {
|
||||
// TODO: if start or end is null, use currently available numbers
|
||||
iterator->sn_next = opt_start ? *opt_start : get_oldest_sequence_number();
|
||||
iterator->sn_end = opt_end ? *opt_end : get_latest_sequence_number();
|
||||
if (get_num_contacts() == 0) {
|
||||
iterator->finished = true; // no contacts -> no iteration :)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
record_t* ens_records_iterator_next(record_iterator_t* iter) {
|
||||
if (iter->finished) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
record_t* next = NULL;
|
||||
|
||||
// What is this?
|
||||
while (next == NULL) {
|
||||
contact_t contact;
|
||||
// try to load the next contact
|
||||
int res = load_contact(&contact, iter->sn_next);
|
||||
|
||||
if (!res) {
|
||||
next = &iter->current;
|
||||
memcpy(&next->associated_encrypted_metadata, &contact.associated_encrypted_metadata, sizeof(associated_encrypted_metadata_t));
|
||||
memcpy(&next->rolling_proximity_identifier, &contact.rolling_proximity_identifier, sizeof(rolling_proximity_identifier_t));
|
||||
memcpy(&next->rssi, &contact.max_rssi, sizeof(rssi_t));
|
||||
memcpy(&next->sn, &iter->sn_next, sizeof(record_sequence_number_t));
|
||||
|
||||
// TODO lome: timestamp?
|
||||
}
|
||||
|
||||
if (sequence_number_eq(iter->sn_next, iter->sn_end)) {
|
||||
iter->finished = true; // this iterator will finish after this execution
|
||||
} else {
|
||||
// increase the current sn
|
||||
iter->sn_next = sequence_number_increment(iter->sn_next);
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
int ens_record_iterator_clear(record_iterator_t* iter) {
|
||||
// TODO: memclear iter->current ?
|
||||
//
|
||||
iter->finished = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata) {
|
||||
record_t* cur = ens_records_iterator_next(iter);
|
||||
bool cont = true;
|
||||
|
||||
while (cur != NULL && cont) {
|
||||
int cb_res = cb(cur, userdata);
|
||||
if (cb_res == ENS_RECORD_ITER_STOP) {
|
||||
cont = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cont) {
|
||||
cb(NULL, userdata); // we call the callback one last time but with null data
|
||||
}
|
||||
return 0;
|
||||
}
|
59
src/records.h
Normal file
59
src/records.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Louis Meyer and Patrick Rathje
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef ENS_RECORDS_H
|
||||
#define ENS_RECORDS_H
|
||||
|
||||
#include "sequencenumber.h"
|
||||
#include "storage.h"
|
||||
|
||||
typedef struct record {
|
||||
record_sequence_number_t sn; // TODO: Convert Sequence Number
|
||||
uint32_t timestamp; // TODO: Seconds from january first 2000 (UTC+0)
|
||||
rssi_t rssi; // TODO: Check correct
|
||||
rolling_proximity_identifier_t rolling_proximity_identifier;
|
||||
associated_encrypted_metadata_t associated_encrypted_metadata;
|
||||
} record_t;
|
||||
|
||||
typedef struct record_iterator {
|
||||
record_t current;
|
||||
record_sequence_number_t sn_next;
|
||||
record_sequence_number_t sn_end; // the last sn to include
|
||||
uint8_t finished;
|
||||
} record_iterator_t;
|
||||
|
||||
// Also uses start and end from storage if NULL pointers given
|
||||
// iterate over a sequence number range of records (Null will select the latest and newest for start / end)
|
||||
// automatically
|
||||
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
||||
record_sequence_number_t* opt_start,
|
||||
record_sequence_number_t* opt_end);
|
||||
|
||||
// TODO: This function should call with the relevant start and end sequence numbers (retrieved through e.g. binary
|
||||
// search / metadata)
|
||||
// TODO: Do we guarantee that higher sequence numbers have at least our timestamp and lower sequence numbers up to our
|
||||
// timestamp?
|
||||
int ens_records_iterator_init_timerange(record_iterator_t* iterator, uint32_t* ts_start, uint32_t* ts_end);
|
||||
|
||||
record_t* ens_records_iterator_next(record_iterator_t* iter);
|
||||
|
||||
int ens_record_iterator_clear(record_iterator_t* iter);
|
||||
|
||||
// TODO: Is a callback the easiest thing to do? -> now it is the iterator :)
|
||||
// TODO: should we really indicated the last record by sending a NULL pointer?
|
||||
typedef uint8_t (*ens_record_iterator_cb_t)(const record_t* record, void* userdata);
|
||||
|
||||
enum {
|
||||
ENS_RECORD_ITER_STOP, // STOP the iteration, this would not result in a NULL callback after the end is reached
|
||||
ENS_RECORD_ITER_CONTINUE, // CONTINUE the iteration, this results in a NULL callback after the end is reached
|
||||
};
|
||||
|
||||
// TODO: this function could be made asynchronous to handle delays in contact_storage reads?!
|
||||
// TODO: How can we handle iteration while records are being added or deleted? (should be safe as long as the
|
||||
// load_contact function is thread safe?!)
|
||||
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata);
|
||||
|
||||
#endif
|
10
src/sequencenumber.c
Normal file
10
src/sequencenumber.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include "sequencenumber.h"
|
||||
|
||||
|
||||
int sequence_number_eq(record_sequence_number_t a, record_sequence_number_t b) {
|
||||
return (a & SN_MASK) == (b & SN_MASK);
|
||||
}
|
||||
|
||||
record_sequence_number_t sequence_number_increment(record_sequence_number_t sn) {
|
||||
return (++sn & SN_MASK);
|
||||
}
|
27
src/sequencenumber.h
Normal file
27
src/sequencenumber.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef SEQUENCENUMBER_H
|
||||
#define SEQUENCENUMBER_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// mask for sequence numbers (2^24 - 1)
|
||||
#define SN_MASK 16777215
|
||||
|
||||
typedef uint32_t record_sequence_number_t;
|
||||
|
||||
/**
|
||||
* Compare to sequence numbers for equality.
|
||||
*
|
||||
* @param a first sequence number
|
||||
* @param b second sequence number
|
||||
* @return 1, if sequence numbers are equal, 0 otherwise.
|
||||
*/
|
||||
int sequence_number_eq(record_sequence_number_t a, record_sequence_number_t b);
|
||||
|
||||
/**
|
||||
* Increment the given sequence number. Wraps around, if 2^24 is reached.
|
||||
*
|
||||
* @param sn sequence number to increment
|
||||
* @return the incremented sequenced number
|
||||
*/
|
||||
record_sequence_number_t sequence_number_increment(record_sequence_number_t sn);
|
||||
#endif
|
@ -25,9 +25,9 @@ inline storage_id_t convert_sn_to_storage_id(record_sequence_number_t sn) {
|
||||
return (storage_id_t)(sn % MAX_CONTACTS) + CONTACTS_OFFSET;
|
||||
}
|
||||
|
||||
void increase_sn_counter() {
|
||||
if (contact_information.count >= MAX_CONTACTS ) {
|
||||
contact_information.oldest_contact++;
|
||||
void increment_storaed_contact_counter() {
|
||||
if (contact_information.count >= MAX_CONTACTS) {
|
||||
contact_information.oldest_contact = sequence_number_increment(contact_information.oldest_contact);
|
||||
}
|
||||
}
|
||||
|
||||
@ -45,24 +45,14 @@ int init_contact_storage(void) {
|
||||
fs.sector_count = SEC_COUNT;
|
||||
|
||||
rc = nvs_init(&fs, DT_CHOSEN_ZEPHYR_FLASH_CONTROLLER_LABEL);
|
||||
|
||||
// char buf[16];
|
||||
// rc = nvs_read(&fs, ADDRESS_ID, &buf, sizeof(buf));
|
||||
// if (rc > 0) { /* item was found, show it */
|
||||
// printk("Id: %d, Address: %s\n", ADDRESS_ID, buf);
|
||||
// } else { /* item was not found, add it */
|
||||
// strcpy(buf, "192.168.1.1");
|
||||
// printk("No address found, adding %s at id %d\n", buf, ADDRESS_ID);
|
||||
// (void)nvs_write(&fs, ADDRESS_ID, &buf, strlen(buf) + 1);
|
||||
// }
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int load_contact(contact_t* dest, record_sequence_number_t sn) {
|
||||
storage_id_t id = convert_sn_to_storage_id(sn);
|
||||
int rc = nvs_read(&fs, id, dest, sizeof(*dest));
|
||||
if(rc <= 0) {
|
||||
if (rc <= 0) {
|
||||
return rc;
|
||||
}
|
||||
return 0;
|
||||
@ -74,7 +64,7 @@ int add_contact(contact_t* src) {
|
||||
|
||||
int rc = nvs_write(&fs, id, src, sizeof(*src));
|
||||
if (rc > 0) {
|
||||
increase_sn_counter();
|
||||
increment_storaed_contact_counter();
|
||||
return 0;
|
||||
}
|
||||
return rc;
|
||||
|
@ -2,9 +2,7 @@
|
||||
#define CONTACT_STORAGE_H
|
||||
|
||||
#include "contacts.h" // Requires contact_t in contacts.h!
|
||||
|
||||
// TODO: This should be masked to k=24 bits
|
||||
typedef uint32_t record_sequence_number_t;
|
||||
#include "sequencenumber.h"
|
||||
|
||||
typedef uint16_t storage_id_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user