Add records api, move sequence numbers into own file, adjust storage api

This commit is contained in:
H1ghBre4k3r 2021-03-17 14:49:07 +01:00 committed by Patrick Rathje
parent 0a5323674a
commit b98eea970c
8 changed files with 180 additions and 20 deletions

View File

@ -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;

View File

@ -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
View 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
View 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
View 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
View 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

View File

@ -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;

View File

@ -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;