From b98eea970cf6c5682c2cc39bb17edc534c320466 Mon Sep 17 00:00:00 2001 From: H1ghBre4k3r Date: Wed, 17 Mar 2021 14:49:07 +0100 Subject: [PATCH] Add records api, move sequence numbers into own file, adjust storage api --- src/contacts.h | 2 +- src/covid_types.h | 2 ++ src/records.c | 74 ++++++++++++++++++++++++++++++++++++++++++++ src/records.h | 59 +++++++++++++++++++++++++++++++++++ src/sequencenumber.c | 10 ++++++ src/sequencenumber.h | 27 ++++++++++++++++ src/storage.c | 22 ++++--------- src/storage.h | 4 +-- 8 files changed, 180 insertions(+), 20 deletions(-) create mode 100644 src/records.c create mode 100644 src/records.h create mode 100644 src/sequencenumber.c create mode 100644 src/sequencenumber.h diff --git a/src/contacts.h b/src/contacts.h index ace1e5b..13b7b51 100644 --- a/src/contacts.h +++ b/src/contacts.h @@ -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; diff --git a/src/covid_types.h b/src/covid_types.h index cec0319..43e28ce 100644 --- a/src/covid_types.h +++ b/src/covid_types.h @@ -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 diff --git a/src/records.c b/src/records.c new file mode 100644 index 0000000..7feeb63 --- /dev/null +++ b/src/records.c @@ -0,0 +1,74 @@ +#include +#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; +} \ No newline at end of file diff --git a/src/records.h b/src/records.h new file mode 100644 index 0000000..4c6fb8e --- /dev/null +++ b/src/records.h @@ -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 \ No newline at end of file diff --git a/src/sequencenumber.c b/src/sequencenumber.c new file mode 100644 index 0000000..c688e7f --- /dev/null +++ b/src/sequencenumber.c @@ -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); +} \ No newline at end of file diff --git a/src/sequencenumber.h b/src/sequencenumber.h new file mode 100644 index 0000000..428f593 --- /dev/null +++ b/src/sequencenumber.h @@ -0,0 +1,27 @@ +#ifndef SEQUENCENUMBER_H +#define SEQUENCENUMBER_H + +#include + +// 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 \ No newline at end of file diff --git a/src/storage.c b/src/storage.c index 0715004..99df8ff 100644 --- a/src/storage.c +++ b/src/storage.c @@ -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; diff --git a/src/storage.h b/src/storage.h index 46c8f9e..17ca635 100644 --- a/src/storage.h +++ b/src/storage.h @@ -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;