mirror of
https://github.com/CovidBraceletPrj/CovidBracelet.git
synced 2024-12-04 16:45:43 +01:00
Refactor and Clean Project for essential functionality
This commit is contained in:
parent
ac320271a0
commit
ee4612104d
1
.gitignore
vendored
1
.gitignore
vendored
@ -47,3 +47,4 @@ massif-*
|
||||
.vscode
|
||||
|
||||
.DS_Store
|
||||
/.idea
|
||||
|
@ -1,25 +0,0 @@
|
||||
#ifndef BLOOM_H
|
||||
#define BLOOM_H
|
||||
|
||||
#include "ens/storage.h"
|
||||
#include "exposure-notification.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t* data;
|
||||
size_t size;
|
||||
} bloom_filter_t;
|
||||
|
||||
/**
|
||||
* Initialize the bloom filter on basis of the already registerred records.
|
||||
*/
|
||||
bloom_filter_t* bloom_init(size_t size);
|
||||
|
||||
void bloom_destroy(bloom_filter_t* bloom);
|
||||
|
||||
// TODO lome: maybe only use RPI (should be sufficient)
|
||||
void bloom_add_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi);
|
||||
|
||||
// TODO lome: maybe only use RPI (should be sufficient)
|
||||
bool bloom_probably_has_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi);
|
||||
|
||||
#endif
|
@ -1,66 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef CONTACTS_H
|
||||
#define CONTACTS_H
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include "covid.h"
|
||||
#include "covid_types.h"
|
||||
#include "ens/storage.h"
|
||||
#include "exposure-notification.h"
|
||||
|
||||
typedef struct {
|
||||
ENIntervalIdentifier interval_identifier;
|
||||
int met;
|
||||
time_t search_start;
|
||||
time_t search_end;
|
||||
} __packed infected_for_interval_ident_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
ENPeriodKey periodKey;
|
||||
time_t start;
|
||||
int met;
|
||||
} __packed period_key_information_t;
|
||||
|
||||
typedef int (*test_func_t)(infected_for_interval_ident_ctx_t* infectedIntervals, int count);
|
||||
|
||||
void print_key(_ENBaseKey* key);
|
||||
void print_rpi(rolling_proximity_identifier_t* rpi);
|
||||
void print_aem(associated_encrypted_metadata_t* aem);
|
||||
|
||||
/**
|
||||
* Register a new record in the system. This includes adding it to the storage and adding it to the bloom filter.
|
||||
*
|
||||
* @param record record to add
|
||||
* @returns 0 in case of success, -ERRNO in case of an error
|
||||
*/
|
||||
int register_record(record_t* record);
|
||||
|
||||
/**
|
||||
* Initialize the contacts module.
|
||||
*/
|
||||
int init_contacts();
|
||||
|
||||
/**
|
||||
* Check for a list of specified interval identifiers, whether they were probably met or not.
|
||||
* @param ctx list of interval identifiers to check
|
||||
* @param count amount of identifiers to check
|
||||
* @return the amount of met intervals, -ERRNO on error
|
||||
*/
|
||||
int check_possible_contacts_for_intervals(infected_for_interval_ident_ctx_t* ctx, int count);
|
||||
|
||||
/**
|
||||
* Check for a list of specified period keys, whether they were probably met or not.
|
||||
* @param ctx list of period keys and their meta information to check
|
||||
* @param count amount of period keys to check
|
||||
* @return -ERRNO on error, 0 otherwise
|
||||
*/
|
||||
int check_possible_contacts_for_periods(period_key_information_t periodKeyInformation[], int count);
|
||||
|
||||
#endif
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef COVID_H
|
||||
#define COVID_H
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
#include "exposure-notification.h"
|
||||
|
||||
typedef struct period{
|
||||
ENPeriodKey periodKey;
|
||||
ENIntervalNumber periodInterval;
|
||||
} __packed period_t;
|
||||
|
||||
int init_covid();
|
||||
int do_covid();
|
||||
|
||||
bool get_infection();
|
||||
void set_infection(bool _infected);
|
||||
unsigned int get_period_cnt_if_infected();
|
||||
period_t* get_period_if_infected(unsigned int id, size_t* size);
|
||||
|
||||
int get_index_by_interval(ENIntervalNumber periodInterval);
|
||||
|
||||
|
||||
void print_periods();
|
||||
#endif
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef COVID_TYPES_H
|
||||
#define COVID_TYPES_H
|
||||
|
||||
#include <exposure-notification.h>
|
||||
#include <zephyr.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#define COVID_ROLLING_PROXIMITY_IDENTIFIER_LEN 16
|
||||
|
||||
typedef ENIntervalIdentifier rolling_proximity_identifier_t;
|
||||
|
||||
typedef struct bt_metadata {
|
||||
uint8_t version;
|
||||
uint8_t tx_power;
|
||||
uint8_t rsv1;
|
||||
uint8_t rsv2;
|
||||
} __packed bt_metadata_t;
|
||||
|
||||
// typedef struct bt_metadata bt_metadata_t;
|
||||
|
||||
typedef struct associated_encrypted_metadata {
|
||||
uint8_t data[sizeof(bt_metadata_t)];
|
||||
} __packed associated_encrypted_metadata_t;
|
||||
|
||||
typedef uint8_t rssi_t;
|
||||
|
||||
#endif
|
@ -1,73 +0,0 @@
|
||||
#ifndef DISPLAY_H
|
||||
#define DISPLAY_H
|
||||
|
||||
/**
|
||||
* @brief Initializes all display elements and adds them to the canvas.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int init_display();
|
||||
|
||||
/**
|
||||
* @brief Updates all information on the display using the get functions, defined by `display.c`. Alternatively the
|
||||
* values of the displayed elements can be set explicitly via set `display_set_<property>`-functions.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int update_display();
|
||||
|
||||
/**
|
||||
* @brief This is the entry point for the display thread. It peridocially updates the display and handles input events.
|
||||
*
|
||||
*/
|
||||
void display_thread(void*, void*, void*);
|
||||
|
||||
/**
|
||||
* @brief Displays a message at the bottom of the display. The message will persist until it is removed expicitly, by calling `display_set_message("")`.
|
||||
*
|
||||
* @param msg A pointer to the string that should be displayed
|
||||
* @return int
|
||||
*/
|
||||
int display_set_message(char* msg);
|
||||
|
||||
/**
|
||||
* @brief Sets the on display clock. The time should have the format `h * 100 + m`. So `display_set_time(1145)` sets the clock to 11:45.
|
||||
*
|
||||
* @param time A number representation of the time
|
||||
* @return int
|
||||
*/
|
||||
int display_set_time(int time);
|
||||
|
||||
/**
|
||||
* @brief Set the battery level percentage.
|
||||
*
|
||||
* @param bat The battery level in percent
|
||||
* @return int
|
||||
*/
|
||||
int display_set_bat(int bat);
|
||||
|
||||
/**
|
||||
* @brief Set the non-volatile memory state.
|
||||
*
|
||||
* @param mem The occupied memory in percent
|
||||
* @return int
|
||||
*/
|
||||
int display_set_mem(int mem);
|
||||
|
||||
/**
|
||||
* @brief Set the number of total registered contacts in the last 14 days.
|
||||
*
|
||||
* @param contacts The number of contacts
|
||||
* @return int
|
||||
*/
|
||||
int display_set_contacts(int contacts);
|
||||
|
||||
/**
|
||||
* @brief Set the number of contacts that were tested positively on Covid and registered in the last 14 days.
|
||||
*
|
||||
* @param risk_contacts The number of risk contacts
|
||||
* @return int
|
||||
*/
|
||||
int display_set_risk_contacts(int risk_contacts);
|
||||
|
||||
#endif
|
@ -1,10 +0,0 @@
|
||||
#ifndef ENS_ERROR_H
|
||||
#define ENS_ERROR_H
|
||||
|
||||
#define ENS_INTERR 1 // internal error
|
||||
#define ENS_NOENT 2 // entry not found or invalid
|
||||
#define ENS_DELENT 3 // entry got deleted
|
||||
#define ENS_ADDRINU 4 // address alread in use or corrupt
|
||||
#define ENS_INVARG 5 // invalid argument
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* 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_iterator {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
record_t current;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
record_sequence_number_t sn_next;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
record_sequence_number_t sn_end; // the last sn to include
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
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: 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, time_t* ts_start, time_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_record function is thread safe?!)
|
||||
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata);
|
||||
|
||||
#endif
|
@ -1,80 +0,0 @@
|
||||
#ifndef CONTACT_STORAGE_H
|
||||
#define CONTACT_STORAGE_H
|
||||
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include "covid_types.h"
|
||||
#include "sequencenumber.h"
|
||||
|
||||
typedef uint64_t storage_id_t;
|
||||
|
||||
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;
|
||||
} __packed record_t;
|
||||
|
||||
typedef struct stored_records_information {
|
||||
record_sequence_number_t oldest_contact;
|
||||
uint32_t count;
|
||||
} stored_records_information_t;
|
||||
|
||||
/**
|
||||
* Initializes the contact storage component
|
||||
* @param clean flag for indicating, if storage shall be init with clean state
|
||||
*
|
||||
* @return 0 for success
|
||||
*/
|
||||
int init_record_storage(bool clean);
|
||||
|
||||
/**
|
||||
* Reset state of record storage.
|
||||
*/
|
||||
void reset_record_storage();
|
||||
|
||||
/**
|
||||
* Loads the record with number sn into the destination struct
|
||||
* @param dest
|
||||
* @param sn
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int load_record(record_t* dest, record_sequence_number_t sn);
|
||||
|
||||
/**
|
||||
* Stores the record from src with number sn, increases latest sequence number
|
||||
* @param sn
|
||||
* @param src
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int add_record(record_t* src);
|
||||
|
||||
/**
|
||||
* Deletes the record from storage with number sn
|
||||
* @param sn the sequence number to delete
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int delete_record(record_sequence_number_t sn);
|
||||
|
||||
/**
|
||||
* TODO: How to handle if none is available?
|
||||
* @return The latest available sequence number (Caution: can actually be lower than the oldes in case of a
|
||||
* wrap-around!)
|
||||
*/
|
||||
record_sequence_number_t get_latest_sequence_number();
|
||||
|
||||
/**
|
||||
* TODO: How to handle if none is available?
|
||||
* @return The oldest available sequence number
|
||||
*/
|
||||
record_sequence_number_t get_oldest_sequence_number();
|
||||
|
||||
/**
|
||||
* @return The amount of contacts, usually get_latest_sequence_number() - get_oldest_sequence_number()
|
||||
*/
|
||||
uint32_t get_num_records();
|
||||
|
||||
int get_sequence_number_interval(record_sequence_number_t* oldest, record_sequence_number_t* latest);
|
||||
|
||||
#endif
|
@ -1,355 +0,0 @@
|
||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
||||
/* Generated from: export.proto */
|
||||
|
||||
#ifndef PROTOBUF_C_export_2eproto__INCLUDED
|
||||
#define PROTOBUF_C_export_2eproto__INCLUDED
|
||||
|
||||
#include <protobuf-c.h>
|
||||
|
||||
PROTOBUF_C__BEGIN_DECLS
|
||||
|
||||
#if PROTOBUF_C_VERSION_NUMBER < 1000000
|
||||
# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.
|
||||
#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION
|
||||
# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct TemporaryExposureKeyExport TemporaryExposureKeyExport;
|
||||
typedef struct SignatureInfo SignatureInfo;
|
||||
typedef struct TemporaryExposureKey TemporaryExposureKey;
|
||||
typedef struct TEKSignatureList TEKSignatureList;
|
||||
typedef struct TEKSignature TEKSignature;
|
||||
|
||||
|
||||
/* --- enums --- */
|
||||
|
||||
/*
|
||||
* Data type representing why this key was published.
|
||||
*/
|
||||
typedef enum _TemporaryExposureKey__ReportType {
|
||||
/*
|
||||
* Never returned by the client API.
|
||||
*/
|
||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__UNKNOWN = 0,
|
||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_TEST = 1,
|
||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_CLINICAL_DIAGNOSIS = 2,
|
||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__SELF_REPORT = 3,
|
||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__RECURSIVE = 4,
|
||||
/*
|
||||
* Used to revoke a key, never returned by client API.
|
||||
*/
|
||||
TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__REVOKED = 5
|
||||
PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(TEMPORARY_EXPOSURE_KEY__REPORT_TYPE)
|
||||
} TemporaryExposureKey__ReportType;
|
||||
|
||||
/* --- messages --- */
|
||||
|
||||
/*
|
||||
* Protobuf definition for exports of confirmed temporary exposure keys.
|
||||
* The full file format is documented under "Exposure Key Export File Format
|
||||
* and Verification" at https://www.google.com/covid19/exposurenotifications/
|
||||
* These files have a 16-byte, space-padded header before the protobuf data
|
||||
* starts. They will be contained in a zip archive, alongside a signature
|
||||
* file verifying the contents.
|
||||
*/
|
||||
struct TemporaryExposureKeyExport
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Time window of keys in this file based on arrival to server, in UTC
|
||||
* seconds. start_timestamp, end_timestamp, and batch_num must be unique
|
||||
* at any given snapshot of the index for a server. If multiple
|
||||
* files are used for a specific time period, and batch_num/batch_size
|
||||
* are both 1 (See below), then offsetting the end_timestamp is the
|
||||
* suggested method for forcing uniqueness.
|
||||
*/
|
||||
protobuf_c_boolean has_start_timestamp;
|
||||
uint64_t start_timestamp;
|
||||
protobuf_c_boolean has_end_timestamp;
|
||||
uint64_t end_timestamp;
|
||||
/*
|
||||
* Region for which these keys came from (e.g., country)
|
||||
*/
|
||||
char *region;
|
||||
/*
|
||||
* E.g., Batch 2 of 10. Ordinal, 1-based numbering.
|
||||
* Note: Not yet supported on iOS. Use values of 1 for both.
|
||||
*/
|
||||
protobuf_c_boolean has_batch_num;
|
||||
int32_t batch_num;
|
||||
protobuf_c_boolean has_batch_size;
|
||||
int32_t batch_size;
|
||||
/*
|
||||
* Information about signatures
|
||||
* If there are multiple entries, they must be ordered in descending
|
||||
* time order by signing key effective time (most recent one first).
|
||||
* There is a limit of 10 signature infos per export file (mobile OS may
|
||||
* not check anything after that).
|
||||
*/
|
||||
size_t n_signature_infos;
|
||||
SignatureInfo **signature_infos;
|
||||
/*
|
||||
* The TemporaryExposureKeys for initial release of keys.
|
||||
* Keys should be included in this list for initial release,
|
||||
* whereas revised or revoked keys should go in revised_keys.
|
||||
*/
|
||||
size_t n_keys;
|
||||
TemporaryExposureKey **keys;
|
||||
/*
|
||||
* TemporaryExposureKeys that have changed status.
|
||||
* Keys should be included in this list if they have changed status
|
||||
* or have been revoked.
|
||||
*/
|
||||
size_t n_revised_keys;
|
||||
TemporaryExposureKey **revised_keys;
|
||||
};
|
||||
#define TEMPORARY_EXPOSURE_KEY_EXPORT__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&temporary_exposure_key_export__descriptor) \
|
||||
, 0, 0, 0, 0, NULL, 0, 0, 0, 0, 0,NULL, 0,NULL, 0,NULL }
|
||||
|
||||
|
||||
struct SignatureInfo
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Key version for rollovers
|
||||
* Must be in character class [a-zA-Z0-9_]. E.g., 'v1'
|
||||
*/
|
||||
char *verification_key_version;
|
||||
/*
|
||||
* Alias with which to identify public key to be used for verification
|
||||
* Must be in character class [a-zA-Z0-9_]
|
||||
* For cross-compatibility with Apple, use MCC
|
||||
* (https://en.wikipedia.org/wiki/Mobile_country_code).
|
||||
*/
|
||||
char *verification_key_id;
|
||||
/*
|
||||
* ASN.1 OID for Algorithm Identifier. Supported algorithms are
|
||||
* either 1.2.840.10045.4.3.2 or 1.2.840.10045.4.3.4
|
||||
*/
|
||||
char *signature_algorithm;
|
||||
};
|
||||
#define SIGNATURE_INFO__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&signature_info__descriptor) \
|
||||
, NULL, NULL, NULL }
|
||||
|
||||
|
||||
struct TemporaryExposureKey
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Key of infected user
|
||||
*/
|
||||
protobuf_c_boolean has_key_data;
|
||||
ProtobufCBinaryData key_data;
|
||||
/*
|
||||
* Varying risks associated with exposure depending on type of verification
|
||||
* Ignored by the v1.5 client API when report_type is set.
|
||||
*/
|
||||
protobuf_c_boolean has_transmission_risk_level PROTOBUF_C__DEPRECATED;
|
||||
int32_t transmission_risk_level PROTOBUF_C__DEPRECATED;
|
||||
/*
|
||||
* The interval number since epoch for which a key starts
|
||||
*/
|
||||
protobuf_c_boolean has_rolling_start_interval_number;
|
||||
int32_t rolling_start_interval_number;
|
||||
/*
|
||||
* Increments of 10 minutes describing how long a key is valid
|
||||
*/
|
||||
/*
|
||||
* defaults to 24 hours
|
||||
*/
|
||||
protobuf_c_boolean has_rolling_period;
|
||||
int32_t rolling_period;
|
||||
/*
|
||||
* Type of diagnosis associated with a key.
|
||||
*/
|
||||
protobuf_c_boolean has_report_type;
|
||||
TemporaryExposureKey__ReportType report_type;
|
||||
/*
|
||||
* Number of days elapsed between symptom onset and the TEK being used.
|
||||
* E.g. 2 means TEK is 2 days after onset of symptoms.
|
||||
*/
|
||||
protobuf_c_boolean has_days_since_onset_of_symptoms;
|
||||
int32_t days_since_onset_of_symptoms;
|
||||
};
|
||||
#define TEMPORARY_EXPOSURE_KEY__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&temporary_exposure_key__descriptor) \
|
||||
, 0, {0,NULL}, 0, 0, 0, 0, 0, 144, 0, TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__UNKNOWN, 0, 0 }
|
||||
|
||||
|
||||
struct TEKSignatureList
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* When there are multiple signatures, they must be sorted in time order
|
||||
* by first effective date for the signing key in descending order.
|
||||
* The most recent effective signing key must appear first.
|
||||
* There is a limit of 10 signature infos per export file (mobile OS may
|
||||
* not check anything after that).
|
||||
*/
|
||||
size_t n_signatures;
|
||||
TEKSignature **signatures;
|
||||
};
|
||||
#define TEKSIGNATURE_LIST__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&teksignature_list__descriptor) \
|
||||
, 0,NULL }
|
||||
|
||||
|
||||
struct TEKSignature
|
||||
{
|
||||
ProtobufCMessage base;
|
||||
/*
|
||||
* Info about the signing key, version, algorithm, etc.
|
||||
*/
|
||||
SignatureInfo *signature_info;
|
||||
/*
|
||||
* E.g., Batch 2 of 10
|
||||
* Must match fields from TemporaryExposureKeyExport, see
|
||||
* documentation on that message.
|
||||
*/
|
||||
protobuf_c_boolean has_batch_num;
|
||||
int32_t batch_num;
|
||||
protobuf_c_boolean has_batch_size;
|
||||
int32_t batch_size;
|
||||
/*
|
||||
* Signature in X9.62 format (ASN.1 SEQUENCE of two INTEGER fields)
|
||||
*/
|
||||
protobuf_c_boolean has_signature;
|
||||
ProtobufCBinaryData signature;
|
||||
};
|
||||
#define TEKSIGNATURE__INIT \
|
||||
{ PROTOBUF_C_MESSAGE_INIT (&teksignature__descriptor) \
|
||||
, NULL, 0, 0, 0, 0, 0, {0,NULL} }
|
||||
|
||||
|
||||
/* TemporaryExposureKeyExport methods */
|
||||
void temporary_exposure_key_export__init
|
||||
(TemporaryExposureKeyExport *message);
|
||||
size_t temporary_exposure_key_export__get_packed_size
|
||||
(const TemporaryExposureKeyExport *message);
|
||||
size_t temporary_exposure_key_export__pack
|
||||
(const TemporaryExposureKeyExport *message,
|
||||
uint8_t *out);
|
||||
size_t temporary_exposure_key_export__pack_to_buffer
|
||||
(const TemporaryExposureKeyExport *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
TemporaryExposureKeyExport *
|
||||
temporary_exposure_key_export__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void temporary_exposure_key_export__free_unpacked
|
||||
(TemporaryExposureKeyExport *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* SignatureInfo methods */
|
||||
void signature_info__init
|
||||
(SignatureInfo *message);
|
||||
size_t signature_info__get_packed_size
|
||||
(const SignatureInfo *message);
|
||||
size_t signature_info__pack
|
||||
(const SignatureInfo *message,
|
||||
uint8_t *out);
|
||||
size_t signature_info__pack_to_buffer
|
||||
(const SignatureInfo *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
SignatureInfo *
|
||||
signature_info__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void signature_info__free_unpacked
|
||||
(SignatureInfo *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* TemporaryExposureKey methods */
|
||||
void temporary_exposure_key__init
|
||||
(TemporaryExposureKey *message);
|
||||
size_t temporary_exposure_key__get_packed_size
|
||||
(const TemporaryExposureKey *message);
|
||||
size_t temporary_exposure_key__pack
|
||||
(const TemporaryExposureKey *message,
|
||||
uint8_t *out);
|
||||
size_t temporary_exposure_key__pack_to_buffer
|
||||
(const TemporaryExposureKey *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
TemporaryExposureKey *
|
||||
temporary_exposure_key__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void temporary_exposure_key__free_unpacked
|
||||
(TemporaryExposureKey *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* TEKSignatureList methods */
|
||||
void teksignature_list__init
|
||||
(TEKSignatureList *message);
|
||||
size_t teksignature_list__get_packed_size
|
||||
(const TEKSignatureList *message);
|
||||
size_t teksignature_list__pack
|
||||
(const TEKSignatureList *message,
|
||||
uint8_t *out);
|
||||
size_t teksignature_list__pack_to_buffer
|
||||
(const TEKSignatureList *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
TEKSignatureList *
|
||||
teksignature_list__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void teksignature_list__free_unpacked
|
||||
(TEKSignatureList *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* TEKSignature methods */
|
||||
void teksignature__init
|
||||
(TEKSignature *message);
|
||||
size_t teksignature__get_packed_size
|
||||
(const TEKSignature *message);
|
||||
size_t teksignature__pack
|
||||
(const TEKSignature *message,
|
||||
uint8_t *out);
|
||||
size_t teksignature__pack_to_buffer
|
||||
(const TEKSignature *message,
|
||||
ProtobufCBuffer *buffer);
|
||||
TEKSignature *
|
||||
teksignature__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data);
|
||||
void teksignature__free_unpacked
|
||||
(TEKSignature *message,
|
||||
ProtobufCAllocator *allocator);
|
||||
/* --- per-message closures --- */
|
||||
|
||||
typedef void (*TemporaryExposureKeyExport_Closure)
|
||||
(const TemporaryExposureKeyExport *message,
|
||||
void *closure_data);
|
||||
typedef void (*SignatureInfo_Closure)
|
||||
(const SignatureInfo *message,
|
||||
void *closure_data);
|
||||
typedef void (*TemporaryExposureKey_Closure)
|
||||
(const TemporaryExposureKey *message,
|
||||
void *closure_data);
|
||||
typedef void (*TEKSignatureList_Closure)
|
||||
(const TEKSignatureList *message,
|
||||
void *closure_data);
|
||||
typedef void (*TEKSignature_Closure)
|
||||
(const TEKSignature *message,
|
||||
void *closure_data);
|
||||
|
||||
/* --- services --- */
|
||||
|
||||
|
||||
/* --- descriptors --- */
|
||||
|
||||
extern const ProtobufCMessageDescriptor temporary_exposure_key_export__descriptor;
|
||||
extern const ProtobufCMessageDescriptor signature_info__descriptor;
|
||||
extern const ProtobufCMessageDescriptor temporary_exposure_key__descriptor;
|
||||
extern const ProtobufCEnumDescriptor temporary_exposure_key__report_type__descriptor;
|
||||
extern const ProtobufCMessageDescriptor teksignature_list__descriptor;
|
||||
extern const ProtobufCMessageDescriptor teksignature__descriptor;
|
||||
|
||||
PROTOBUF_C__END_DECLS
|
||||
|
||||
|
||||
#endif /* PROTOBUF_C_export_2eproto__INCLUDED */
|
@ -1,41 +0,0 @@
|
||||
#ifndef EXTRACT_KEYS_H
|
||||
#define EXTRACT_KEYS_H
|
||||
|
||||
#include "export.pb-c.h"
|
||||
|
||||
/**
|
||||
* @brief Process a key. This function could trigger the comparision between the key and those registered by the ENS.
|
||||
*
|
||||
* @param key A pointer to the Exposure key data structure
|
||||
*/
|
||||
void process_key(TemporaryExposureKey* key);
|
||||
|
||||
/**
|
||||
* @brief Generates a protocol buffer containing dummy keys.
|
||||
*
|
||||
* @param buffer_pointer A pointer to the pointer which will be used to reference the buffer externally. This will be
|
||||
* set to the memory area allocated to store the protocol buffer.
|
||||
* @param num_keys The number of keys that will be generated
|
||||
* @return size_t The size of the protocol buffer
|
||||
*/
|
||||
size_t generate_keys(uint8_t** buffer_pointer, int num_keys);
|
||||
|
||||
/**
|
||||
* @brief Unpacks the protocol buffer and iterates the `process_key` function over all keys.
|
||||
*
|
||||
* @param buf a pointer to the buffer
|
||||
* @param buf_size the size of the buffer in bytes
|
||||
* @return int
|
||||
*/
|
||||
int unpack_keys(uint8_t* buf, size_t buf_size);
|
||||
|
||||
/**
|
||||
* @brief Generates an protocol buffer with a specified number of keys and measures the time to execute `unpack_keys`,
|
||||
* which unpacks the protocol buffer and iterates `process_key` over the keys.
|
||||
*
|
||||
* @param num_keys the number of keys that will be created
|
||||
* @return int
|
||||
*/
|
||||
int test_unpacking(int num_keys);
|
||||
|
||||
#endif
|
@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef GATT_SERVICE_H
|
||||
#define GATT_SERVICE_H
|
||||
|
||||
int init_gatt(void);
|
||||
int do_gatt(void);
|
||||
|
||||
#endif
|
151
include/record_storage.h
Normal file
151
include/record_storage.h
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef RECORD_STORAGE_H
|
||||
#define RECORD_STORAGE_H
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include "utility/sequencenumber.h"
|
||||
#include <exposure-notification.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* RECORD STORAGE
|
||||
*/
|
||||
typedef uint64_t storage_id_t;
|
||||
|
||||
typedef struct bt_metadata {
|
||||
uint8_t version;
|
||||
uint8_t tx_power;
|
||||
uint8_t rsv1;
|
||||
uint8_t rsv2;
|
||||
} __packed bt_metadata_t;
|
||||
|
||||
typedef struct associated_encrypted_metadata {
|
||||
uint8_t data[sizeof(bt_metadata_t)];
|
||||
} __packed associated_encrypted_metadata_t;
|
||||
|
||||
typedef struct record {
|
||||
record_sequence_number_t sn; // TODO: Convert Sequence Number
|
||||
uint32_t timestamp; // TODO: Seconds from january first 2000 (UTC+0)
|
||||
uint8_t rssi; // TODO: Check correct
|
||||
ENIntervalIdentifier rolling_proximity_identifier;
|
||||
associated_encrypted_metadata_t associated_encrypted_metadata;
|
||||
} __packed record_t;
|
||||
|
||||
typedef struct stored_records_information {
|
||||
record_sequence_number_t oldest_contact;
|
||||
uint32_t count;
|
||||
} stored_records_information_t;
|
||||
|
||||
/**
|
||||
* Initializes the contact storage component
|
||||
* @param clean flag for indicating, if storage shall be init with clean state
|
||||
*
|
||||
* @return 0 for success
|
||||
*/
|
||||
int record_storage_init(bool clean);
|
||||
|
||||
/**
|
||||
* Reset state of record storage.
|
||||
*/
|
||||
void reset_record_storage();
|
||||
|
||||
/**
|
||||
* Loads the record with number sn into the destination struct
|
||||
* @param dest
|
||||
* @param sn
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int load_record(record_t* dest, record_sequence_number_t sn);
|
||||
|
||||
/**
|
||||
* Stores the record from src with number sn, increases latest sequence number
|
||||
* @param sn
|
||||
* @param src
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int add_record(record_t* src);
|
||||
|
||||
/**
|
||||
* Deletes the record from storage with number sn
|
||||
* @param sn the sequence number to delete
|
||||
* @return 0 in case of success
|
||||
*/
|
||||
int delete_record(record_sequence_number_t sn);
|
||||
|
||||
/**
|
||||
* TODO: How to handle if none is available?
|
||||
* @return The latest available sequence number (Caution: can actually be lower than the oldes in case of a
|
||||
* wrap-around!)
|
||||
*/
|
||||
record_sequence_number_t get_latest_sequence_number();
|
||||
|
||||
/**
|
||||
* TODO: How to handle if none is available?
|
||||
* @return The oldest available sequence number
|
||||
*/
|
||||
record_sequence_number_t get_oldest_sequence_number();
|
||||
|
||||
/**
|
||||
* @return The amount of contacts, usually get_latest_sequence_number() - get_oldest_sequence_number()
|
||||
*/
|
||||
uint32_t get_num_records();
|
||||
|
||||
int get_sequence_number_interval(record_sequence_number_t* oldest, record_sequence_number_t* latest);
|
||||
|
||||
/**
|
||||
* RECORD ITERATOR
|
||||
*/
|
||||
typedef struct record_iterator {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
record_t current;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
record_sequence_number_t sn_next;
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
record_sequence_number_t sn_end; // the last sn to include
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
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: 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, time_t* ts_start, time_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_record function is thread safe?!)
|
||||
uint8_t ens_records_iterate_with_callback(record_iterator_t* iter, ens_record_iterator_cb_t cb, void* userdata);
|
||||
|
||||
#endif
|
13
include/sync_service.h
Normal file
13
include/sync_service.h
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef SYNC_SERVICE_H
|
||||
#define SYNC_SERVICE_H
|
||||
|
||||
int sync_service_init(void);
|
||||
int sync_service_run(void);
|
||||
|
||||
#endif
|
35
include/tek_storage.h
Normal file
35
include/tek_storage.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#ifndef tek_storage_H
|
||||
#define tek_storage_H
|
||||
|
||||
#include <exposure-notification.h>
|
||||
#include <zephyr/types.h>
|
||||
#include "utility/sequencenumber.h"
|
||||
#include "record_storage.h"
|
||||
|
||||
typedef struct tek {
|
||||
uint32_t timestamp; // Seconds from january first 2000 (UTC+0)
|
||||
ENPeriodKey tek; // the temporary exposure key
|
||||
} __packed tek_t;
|
||||
|
||||
/**
|
||||
* Initializes the contact storage component
|
||||
* @param clean flag for indicating, if storage shall be init with clean state
|
||||
*
|
||||
* @return 0 for success
|
||||
*/
|
||||
int tek_storage_init(bool clean);
|
||||
|
||||
int tek_storage_add(tek_t* src);
|
||||
int tek_storage_delete(tek_t* src);
|
||||
|
||||
/**
|
||||
* Returns 0 on success, else non zero (if none available)
|
||||
*/
|
||||
int tek_storage_get_latest_at_ts(tek_t* dest, uint32_t timestamp);
|
||||
|
||||
#endif
|
@ -1,14 +1,13 @@
|
||||
/* io.h - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef IO_H
|
||||
#define IO_H
|
||||
#ifndef TRACING_H
|
||||
#define TRACING_H
|
||||
|
||||
int init_io();
|
||||
int tracing_init(void);
|
||||
int tracing_run(void);
|
||||
|
||||
#endif
|
@ -1,9 +0,0 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
// TODO: We should use timeutil_sync
|
||||
|
||||
// return the current unix timestamp in seconds
|
||||
uint32_t time_get_unix_seconds();
|
||||
|
||||
#endif // UTIL_H
|
@ -7,6 +7,12 @@
|
||||
#include <stdint.h>
|
||||
#include <storage/flash_map.h>
|
||||
|
||||
#define ENS_INTERR 1 // internal error
|
||||
#define ENS_NOENT 2 // entry not found or invalid
|
||||
#define ENS_DELENT 3 // entry got deleted
|
||||
#define ENS_ADDRINU 4 // address alread in use or corrupt
|
||||
#define ENS_INVARG 5 // invalid argument
|
||||
|
||||
typedef struct ens_fs {
|
||||
/**
|
||||
* Flash area for this file system.
|
16
include/utility/util.h
Normal file
16
include/utility/util.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include <exposure-notification.h>
|
||||
#include "../record_storage.h" // TODO: this dependency is not great...
|
||||
|
||||
// TODO: We should use timeutil_sync
|
||||
|
||||
// return the current unix timestamp in seconds
|
||||
uint32_t time_get_unix_seconds();
|
||||
|
||||
void print_key(_ENBaseKey* key);
|
||||
void print_rpi(ENIntervalIdentifier* rpi);
|
||||
void print_aem(associated_encrypted_metadata_t* aem);
|
||||
|
||||
#endif // UTIL_H
|
@ -16,7 +16,7 @@ platform = nordicnrf52@7.0.0
|
||||
board = nrf52840_dk
|
||||
framework = zephyr
|
||||
monitor_speed = 115200
|
||||
upload_protocol = jlink
|
||||
;upload_protocol = jlink
|
||||
test_ignore = test_desktop
|
||||
build_flags =
|
||||
-Iinclude/tls_config
|
||||
@ -28,12 +28,12 @@ lib_deps =
|
||||
prathje/exposure-notification @ ^0.1
|
||||
lib_ignore =
|
||||
mbedtls
|
||||
src_filter = -<../src/main_test.c>
|
||||
;src_filter = -<../src/main_test.c>
|
||||
|
||||
[env:nrf52840_dk_test]
|
||||
src_filter = -<../src/main.c>
|
||||
extends = env:nrf52840_dk
|
||||
board = nrf52840_mdk
|
||||
;[env:nrf52840_dk_test]
|
||||
;src_filter = -<../src/main.c>
|
||||
;extends = env:nrf52840_dk
|
||||
;board = nrf52840_mdk
|
||||
|
||||
|
||||
[env:nrf52840_mdk]
|
||||
|
46
src/bloom.c
46
src/bloom.c
@ -1,46 +0,0 @@
|
||||
#include "bloom.h"
|
||||
#include "ens/storage.h"
|
||||
#include "exposure-notification.h"
|
||||
|
||||
bloom_filter_t* bloom_init(size_t size) {
|
||||
bloom_filter_t* bloom = k_calloc(1, sizeof(bloom_filter_t));
|
||||
if (!bloom) {
|
||||
return NULL;
|
||||
}
|
||||
bloom->size = size;
|
||||
bloom->data = k_calloc(size, sizeof(uint8_t));
|
||||
if (!bloom->data) {
|
||||
bloom->size = 0;
|
||||
k_free(bloom);
|
||||
return NULL;
|
||||
}
|
||||
return bloom;
|
||||
}
|
||||
|
||||
void bloom_destroy(bloom_filter_t* bloom) {
|
||||
if (bloom) {
|
||||
k_free(bloom->data);
|
||||
k_free(bloom);
|
||||
}
|
||||
}
|
||||
|
||||
void bloom_add_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi) {
|
||||
uint8_t* data = bloom->data;
|
||||
for (int i = 0; i < sizeof(*rpi); i += 2) {
|
||||
uint32_t hash = (rpi->b[i] << 8) | rpi->b[i + 1];
|
||||
hash %= bloom->size * 8;
|
||||
data[hash / 8] |= 1 << (hash % 8);
|
||||
}
|
||||
}
|
||||
|
||||
bool bloom_probably_has_record(bloom_filter_t* bloom, ENIntervalIdentifier* rpi) {
|
||||
uint8_t* data = bloom->data;
|
||||
for (int i = 0; i < sizeof(*rpi); i += 2) {
|
||||
uint32_t hash = (rpi->b[i] << 8) | rpi->b[i + 1];
|
||||
hash %= bloom->size * 8;
|
||||
if (!(data[hash / 8] & (1 << (hash % 8)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
328
src/contacts.c
328
src/contacts.c
@ -1,328 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <sys/printk.h>
|
||||
#include <sys/util.h>
|
||||
#include <timing/timing.h>
|
||||
#include <zephyr.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#include <device.h>
|
||||
#include <devicetree.h>
|
||||
#include <drivers/gpio.h>
|
||||
|
||||
#include "bloom.h"
|
||||
#include "contacts.h"
|
||||
#include "covid.h"
|
||||
#include "covid_types.h"
|
||||
#include "ens/records.h"
|
||||
#include "ens/storage.h"
|
||||
#include "exposure-notification.h"
|
||||
|
||||
// #define CONFIG_INTERVAL_SPREAD 100
|
||||
|
||||
void print_key(_ENBaseKey* key) {
|
||||
for (int i = 0; i < sizeof(key->b); i++) {
|
||||
printk("%02x", key->b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_rpi(rolling_proximity_identifier_t* rpi) {
|
||||
for (int i = 0; i < sizeof(rolling_proximity_identifier_t); i++) {
|
||||
printk("%02x", rpi->b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_aem(associated_encrypted_metadata_t* aem) {
|
||||
for (int i = 0; i < sizeof(associated_encrypted_metadata_t); i++) {
|
||||
printk("%02x", aem->data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int register_record(record_t* record) {
|
||||
return add_record(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* Simple implementation, where an iterator is created for every element in the passed arrray.
|
||||
*/
|
||||
int get_number_of_infected_for_multiple_intervals_simple(infected_for_interval_ident_ctx_t* ctx, int count) {
|
||||
record_iterator_t iterator;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!ctx[i].met) {
|
||||
continue;
|
||||
}
|
||||
ctx[i].met = 0;
|
||||
int rc = ens_records_iterator_init_timerange(&iterator, &ctx[i].search_start, &ctx[i].search_end);
|
||||
if (rc) {
|
||||
// on error, skip this rpi
|
||||
continue;
|
||||
}
|
||||
record_t* current;
|
||||
while ((current = ens_records_iterator_next(&iterator))) {
|
||||
if (memcmp(&(current->rolling_proximity_identifier), &ctx[i].interval_identifier,
|
||||
sizeof(rolling_proximity_identifier_t)) == 0) {
|
||||
ctx[i].met++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the bloom filter with all stored records.
|
||||
*/
|
||||
void fill_bloom_with_stored_records(bloom_filter_t* bloom) {
|
||||
// init iterator for filling bloom filter
|
||||
record_iterator_t iterator;
|
||||
int rc = ens_records_iterator_init_timerange(&iterator, NULL, NULL);
|
||||
if (rc) {
|
||||
printk("init iterator failed0 (err %d)\n", rc);
|
||||
return;
|
||||
}
|
||||
|
||||
// fill bloom filter with records
|
||||
record_t* current;
|
||||
while ((current = ens_records_iterator_next(&iterator))) {
|
||||
bloom_add_record(bloom, &(current->rolling_proximity_identifier));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the bloom filter with flash records and test passed RPIs against it.
|
||||
*/
|
||||
int64_t bloom_filter(infected_for_interval_ident_ctx_t* ctx, int count) {
|
||||
bloom_filter_t* bloom = bloom_init(get_num_records() * 2);
|
||||
if (!bloom) {
|
||||
printk("bloom init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fill_bloom_with_stored_records(bloom);
|
||||
|
||||
// test bloom performance
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (bloom_probably_has_record(bloom, &ctx[i].interval_identifier)) {
|
||||
ctx[i].met++;
|
||||
}
|
||||
}
|
||||
bloom_destroy(bloom);
|
||||
|
||||
return get_number_of_infected_for_multiple_intervals_simple(ctx, count);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// FILL TEST DATA //
|
||||
////////////////////
|
||||
|
||||
static ENPeriodKey infectedPeriodKey = {
|
||||
.b = {0x75, 0xc7, 0x34, 0xc6, 0xdd, 0x1a, 0x78, 0x2d, 0xe7, 0xa9, 0x65, 0xda, 0x5e, 0xb9, 0x31, 0x25}};
|
||||
static ENPeriodKey dummyPeriodKey = {
|
||||
.b = {0x89, 0xa7, 0x34, 0xc6, 0xdd, 0x1a, 0x14, 0xda, 0xe7, 0x00, 0x65, 0xda, 0x6a, 0x9b, 0x13, 0x52}};
|
||||
static ENPeriodKey testKey = {
|
||||
.b = {0x89, 0xa7, 0x72, 0xc6, 0xdd, 0x10, 0x14, 0xda, 0xe7, 0x00, 0x65, 0xda, 0x8a, 0x9b, 0x13, 0x52}};
|
||||
|
||||
static ENPeriodIdentifierKey infectedPik;
|
||||
static ENPeriodIdentifierKey dummyPik;
|
||||
static ENPeriodIdentifierKey testPik;
|
||||
|
||||
void fill_test_rki_data(infected_for_interval_ident_ctx_t* infectedIntervals, int count) {
|
||||
int totalTime = EN_TEK_ROLLING_PERIOD * EN_INTERVAL_LENGTH;
|
||||
int stepSize = totalTime / count;
|
||||
for (int i = 0; i < count; i++) {
|
||||
int intervalNumber = (i * stepSize) / EN_INTERVAL_LENGTH;
|
||||
en_derive_interval_identifier(&infectedIntervals[i].interval_identifier, &infectedPik, intervalNumber);
|
||||
infectedIntervals[i].met = 0;
|
||||
infectedIntervals[i].search_start = i < 3 ? 0 : (i - 2) * stepSize;
|
||||
infectedIntervals[i].search_end = (i + 2) * stepSize;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// MEASURING FUNC //
|
||||
////////////////////
|
||||
|
||||
void measure_perf(infected_for_interval_ident_ctx_t testIntervals[], int count) {
|
||||
const char* label = "bloom filter";
|
||||
printk("---------------------------\n'%s': starting measurement\n", label);
|
||||
|
||||
// fill_test_rki_data(infectedIntervals, count);
|
||||
|
||||
// setup our ordered array with met RPIs
|
||||
printk("Starting measurements with %d RPIs to seach and an infection rate of %d\n", count,
|
||||
CONFIG_TEST_INFECTED_RATE);
|
||||
|
||||
timing_t start_time, end_time;
|
||||
uint64_t total_cycles;
|
||||
uint64_t total_ns;
|
||||
|
||||
timing_init();
|
||||
timing_start();
|
||||
start_time = timing_counter_get();
|
||||
|
||||
check_possible_contacts_for_intervals(testIntervals, count);
|
||||
|
||||
end_time = timing_counter_get();
|
||||
|
||||
total_cycles = timing_cycles_get(&start_time, &end_time);
|
||||
total_ns = timing_cycles_to_ns(total_cycles);
|
||||
|
||||
timing_stop();
|
||||
|
||||
printk("\n'%s' took %lld ms\n---------------------------\n", label, total_ns / 1000000);
|
||||
}
|
||||
|
||||
void check_results(infected_for_interval_ident_ctx_t testIntervals[], int count) {
|
||||
int counter = 0;
|
||||
for (int i = 0; i < count / 2; i++) {
|
||||
counter += CONFIG_TEST_RECORDS_PER_INTERVAL * CONFIG_TEST_INFECTED_RATE;
|
||||
int met = counter / 100;
|
||||
counter %= 100;
|
||||
if (testIntervals[i].met != met) {
|
||||
printk("interval %d should have been met %d times (met %d)\n", i, met, testIntervals[i].met);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = count / 2; j < count; j++) {
|
||||
if (testIntervals[j].met) {
|
||||
printk("infected interval should not have been met (interval %d)\n", j);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printk("all results are as expected!\n");
|
||||
}
|
||||
|
||||
int reverse_bloom_filter(infected_for_interval_ident_ctx_t* ctx, int count) {
|
||||
bloom_filter_t* bloom = bloom_init(count * 2);
|
||||
if (!bloom) {
|
||||
printk("bloom init failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// init bloom filter with passed records
|
||||
for (int i = 0; i < count; i++) {
|
||||
bloom_add_record(bloom, &ctx[i].interval_identifier);
|
||||
}
|
||||
|
||||
int rc = 0;
|
||||
|
||||
// init iterator over the entire storage
|
||||
record_iterator_t iterator;
|
||||
rc = ens_records_iterator_init_timerange(&iterator, NULL, NULL);
|
||||
if (rc) {
|
||||
printk("init iterator failed (err %d)\n", rc);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
record_t* current;
|
||||
while ((current = ens_records_iterator_next(&iterator))) {
|
||||
if (bloom_probably_has_record(bloom, &(current->rolling_proximity_identifier))) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (memcmp(&(current->rolling_proximity_identifier), &ctx[i].interval_identifier,
|
||||
sizeof(current->rolling_proximity_identifier)) == 0) {
|
||||
ctx[i].met++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
// destroy bloom filter after things are finished
|
||||
bloom_destroy(bloom);
|
||||
return rc;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// SETUP DATA //
|
||||
////////////////////
|
||||
|
||||
void setup_test_data(infected_for_interval_ident_ctx_t testIntervals[], int count) {
|
||||
en_derive_period_identifier_key(&infectedPik, &infectedPeriodKey);
|
||||
en_derive_period_identifier_key(&dummyPik, &dummyPeriodKey);
|
||||
en_derive_period_identifier_key(&testPik, &testKey);
|
||||
|
||||
int counter = 0;
|
||||
for (int i = 0; i < EN_TEK_ROLLING_PERIOD; i++) {
|
||||
record_t infectedRecord;
|
||||
record_t dummyRecord;
|
||||
en_derive_interval_identifier((ENIntervalIdentifier*)&infectedRecord.rolling_proximity_identifier, &infectedPik,
|
||||
i);
|
||||
en_derive_interval_identifier((ENIntervalIdentifier*)&dummyRecord.rolling_proximity_identifier, &dummyPik, i);
|
||||
|
||||
for (int j = 0; j < CONFIG_TEST_RECORDS_PER_INTERVAL; j++) {
|
||||
counter += CONFIG_TEST_INFECTED_RATE;
|
||||
record_t* curRecord;
|
||||
if (counter >= 100) {
|
||||
counter -= 100;
|
||||
curRecord = &infectedRecord;
|
||||
} else {
|
||||
curRecord = &dummyRecord;
|
||||
}
|
||||
curRecord->timestamp = i * EN_INTERVAL_LENGTH + j * (EN_INTERVAL_LENGTH / CONFIG_TEST_RECORDS_PER_INTERVAL);
|
||||
int rc = add_record(curRecord);
|
||||
if (rc) {
|
||||
printk("err %d\n", rc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < count / 2; i++) {
|
||||
en_derive_interval_identifier(&testIntervals[i].interval_identifier, &infectedPik, i);
|
||||
testIntervals[i].met = 0;
|
||||
testIntervals[i].search_start = MAX(0, (i * EN_INTERVAL_LENGTH - 2 * 60 * 60));
|
||||
testIntervals[i].search_end = i * EN_INTERVAL_LENGTH + 2 * 60 * 60;
|
||||
|
||||
int j = i + count / 2;
|
||||
en_derive_interval_identifier(&testIntervals[j].interval_identifier, &testPik, i);
|
||||
testIntervals[j].met = 0;
|
||||
testIntervals[j].search_start = MAX(0, (i * EN_INTERVAL_LENGTH - 2 * 60 * 60));
|
||||
testIntervals[j].search_end = i * EN_INTERVAL_LENGTH + 2 * 60 * 60;
|
||||
}
|
||||
}
|
||||
|
||||
int init_contacts() {
|
||||
#if CONFIG_CONTACTS_PERFORM_RISC_CHECK_TEST
|
||||
static infected_for_interval_ident_ctx_t testIntervals[EN_TEK_ROLLING_PERIOD * 2];
|
||||
|
||||
reset_record_storage();
|
||||
setup_test_data(testIntervals, EN_TEK_ROLLING_PERIOD * 2);
|
||||
|
||||
measure_perf(testIntervals, EN_TEK_ROLLING_PERIOD * 2);
|
||||
check_results(testIntervals, EN_TEK_ROLLING_PERIOD * 2);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_possible_contacts_for_intervals(infected_for_interval_ident_ctx_t* ctx, int count) {
|
||||
#if CONFIG_CONTACTS_BLOOM_REVERSE
|
||||
return reverse_bloom_filter(ctx, count);
|
||||
#else
|
||||
return bloom_filter(ctx, count);
|
||||
#endif
|
||||
}
|
||||
|
||||
int check_possible_contacts_for_periods(period_key_information_t periodKeyInformation[], int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
static infected_for_interval_ident_ctx_t intervalIdents[EN_TEK_ROLLING_PERIOD];
|
||||
int periodStart = en_get_interval_number(periodKeyInformation[i].start);
|
||||
for (int interval = 0; interval < EN_TEK_ROLLING_PERIOD; interval++) {
|
||||
en_derive_interval_identifier(&intervalIdents[interval].interval_identifier,
|
||||
&periodKeyInformation[i].periodKey, periodStart + interval);
|
||||
}
|
||||
int rc = check_possible_contacts_for_intervals(intervalIdents, 0);
|
||||
if (rc < 0) {
|
||||
return rc;
|
||||
}
|
||||
periodKeyInformation[i].met = rc;
|
||||
}
|
||||
return 0;
|
||||
}
|
258
src/display.c
258
src/display.c
@ -1,258 +0,0 @@
|
||||
#if CONFIG_DISPLAY
|
||||
#include <device.h>
|
||||
#include <drivers/display.h>
|
||||
#include <lvgl.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#include "display.h"
|
||||
|
||||
K_THREAD_STACK_DEFINE(display_stack_area, 5000);
|
||||
|
||||
#if CONFIG_DISPLAY
|
||||
const struct device* display_dev;
|
||||
lv_obj_t* display_center_pane;
|
||||
lv_obj_t* display_top_bar;
|
||||
lv_obj_t* display_bot_bar;
|
||||
lv_obj_t* display_contacts_label;
|
||||
lv_obj_t* display_risk_contacts_label;
|
||||
lv_obj_t* risk_contacts_button;
|
||||
lv_obj_t* display_clock_label;
|
||||
lv_obj_t* display_battery_label;
|
||||
lv_obj_t* display_memory_label;
|
||||
lv_obj_t* display_msg_label;
|
||||
lv_style_t green_button_style;
|
||||
lv_style_t yellow_button_style;
|
||||
lv_style_t red_button_style;
|
||||
#endif
|
||||
|
||||
|
||||
int get_battery_percentage() {
|
||||
// TODO: Implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_memory_percentage() {
|
||||
// TODO: Implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_time() {
|
||||
// TODO: Implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_contacts() {
|
||||
// TODO: Implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_risk_contacts() {
|
||||
// TODO: Implement
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_DISPLAY
|
||||
|
||||
void display_thread(void* arg1, void* arg2, void* arg3) {
|
||||
static uint32_t sleep_time;
|
||||
while (1) {
|
||||
sleep_time = lv_task_handler();
|
||||
update_display();
|
||||
k_msleep(sleep_time);
|
||||
}
|
||||
}
|
||||
|
||||
int init_styles() {
|
||||
lv_style_init(&green_button_style);
|
||||
lv_style_init(&yellow_button_style);
|
||||
lv_style_init(&red_button_style);
|
||||
|
||||
// Properties for all styles
|
||||
lv_style_set_bg_opa(&green_button_style, LV_STATE_DEFAULT, LV_OPA_COVER);
|
||||
lv_style_set_pad_top(&green_button_style, LV_STATE_DEFAULT, 10);
|
||||
lv_style_set_pad_bottom(&green_button_style, LV_STATE_DEFAULT, 10);
|
||||
lv_style_set_pad_left(&green_button_style, LV_STATE_DEFAULT, 10);
|
||||
lv_style_set_pad_right(&green_button_style, LV_STATE_DEFAULT, 10);
|
||||
lv_style_set_border_width(&green_button_style, LV_STATE_DEFAULT, 1);
|
||||
lv_style_set_radius(&green_button_style, LV_STATE_DEFAULT, 10);
|
||||
|
||||
lv_style_copy(&yellow_button_style, &green_button_style);
|
||||
lv_style_copy(&red_button_style, &green_button_style);
|
||||
|
||||
// Set different colors
|
||||
lv_style_set_bg_color(&green_button_style, LV_STATE_DEFAULT, LV_COLOR_GREEN);
|
||||
lv_style_set_text_color(&green_button_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_style_set_bg_color(&yellow_button_style, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
|
||||
lv_style_set_text_color(&yellow_button_style, LV_STATE_DEFAULT, LV_COLOR_BLACK);
|
||||
lv_style_set_bg_color(&red_button_style, LV_STATE_DEFAULT, LV_COLOR_RED);
|
||||
lv_style_set_text_color(&red_button_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update_display() {
|
||||
display_set_contacts(get_contacts());
|
||||
display_set_risk_contacts(get_risk_contacts());
|
||||
display_set_time(get_time());
|
||||
display_set_bat(get_battery_percentage());
|
||||
display_set_mem(get_memory_percentage());
|
||||
|
||||
lv_task_handler();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_display() {
|
||||
init_styles();
|
||||
|
||||
display_dev = device_get_binding(CONFIG_LVGL_DISPLAY_DEV_NAME);
|
||||
|
||||
if (display_dev == NULL) {
|
||||
printk("device not found. Aborting test.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
display_top_bar = lv_cont_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_width(display_top_bar, lv_obj_get_width(lv_scr_act()));
|
||||
lv_cont_set_layout(display_top_bar, LV_LAYOUT_PRETTY_TOP);
|
||||
|
||||
display_bot_bar = lv_cont_create(lv_scr_act(), NULL);
|
||||
lv_obj_set_width(display_bot_bar, lv_obj_get_width(lv_scr_act()));
|
||||
lv_cont_set_layout(display_bot_bar, LV_LAYOUT_PRETTY_BOTTOM);
|
||||
|
||||
display_center_pane = lv_cont_create(lv_scr_act(), NULL);
|
||||
lv_obj_align(display_center_pane, display_top_bar, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
lv_obj_set_width(display_center_pane, lv_obj_get_width(lv_scr_act()));
|
||||
lv_obj_set_height(display_center_pane, lv_obj_get_height(lv_scr_act()) - lv_obj_get_height(display_top_bar) - lv_obj_get_height(display_bot_bar));
|
||||
lv_cont_set_layout(display_center_pane, LV_LAYOUT_COLUMN_MID);
|
||||
|
||||
lv_obj_align(display_bot_bar, display_center_pane, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
||||
|
||||
display_contacts_label = lv_label_create(display_center_pane, NULL);
|
||||
lv_obj_set_height_margin(display_contacts_label, 20);
|
||||
lv_label_set_text(display_contacts_label, "");
|
||||
|
||||
if (IS_ENABLED(CONFIG_LVGL_POINTER_KSCAN)) {
|
||||
risk_contacts_button = lv_btn_create(display_center_pane, NULL);
|
||||
lv_btn_set_fit(risk_contacts_button, LV_FIT_TIGHT);
|
||||
display_risk_contacts_label = lv_label_create(risk_contacts_button, NULL);
|
||||
} else {
|
||||
display_risk_contacts_label = lv_label_create(display_center_pane, NULL);
|
||||
}
|
||||
|
||||
lv_obj_set_height_margin(display_risk_contacts_label, 20);
|
||||
lv_label_set_text(display_risk_contacts_label, "");
|
||||
|
||||
display_memory_label = lv_label_create(display_top_bar, NULL);
|
||||
lv_obj_set_width_margin(display_memory_label, 10);
|
||||
lv_label_set_text(display_memory_label, "");
|
||||
|
||||
display_clock_label = lv_label_create(display_top_bar, NULL);
|
||||
lv_obj_set_width_margin(display_clock_label, 10);
|
||||
lv_label_set_text(display_clock_label, "");
|
||||
|
||||
display_battery_label = lv_label_create(display_top_bar, NULL);
|
||||
lv_obj_set_width_margin(display_battery_label, 10);
|
||||
lv_label_set_text(display_battery_label, "");
|
||||
|
||||
display_msg_label = lv_label_create(display_bot_bar, NULL);
|
||||
lv_label_set_text(display_msg_label, "");
|
||||
|
||||
static struct k_thread display_thread_data;
|
||||
k_thread_create(&display_thread_data, display_stack_area, K_THREAD_STACK_SIZEOF(display_stack_area), display_thread, NULL, NULL, NULL, 0, 0, K_NO_WAIT);
|
||||
|
||||
display_blanking_off(display_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_message(char* msg) {
|
||||
lv_label_set_text(display_msg_label, msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_time(int time) {
|
||||
lv_label_set_text_fmt(display_clock_label, "%d:%d", time / 100, time % 100)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_bat(int bat) {
|
||||
lv_label_set_text_fmt(display_battery_label, "Bat: %d%%", bat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_mem(int mem) {
|
||||
lv_label_set_text_fmt(display_memory_label, "Mem: %d%%", mem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_contacts(int contacts) {
|
||||
lv_label_set_text_fmt(display_contacts_label, "Number of contacts: %d,\nfrom which", contacts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_risk_contacts(int risk_contacts) {
|
||||
lv_label_set_text_fmt(display_risk_contacts_label, "%d are risk contacts.", risk_contacts);
|
||||
|
||||
if (risk_contacts == 0) {
|
||||
// Set Button green
|
||||
lv_obj_reset_style_list(risk_contacts_button, LV_OBJ_PART_MAIN);
|
||||
lv_obj_add_style(risk_contacts_button, LV_BTN_PART_MAIN, &green_button_style);
|
||||
} else if (risk_contacts < 5) {
|
||||
// Set Button yellow
|
||||
lv_obj_reset_style_list(risk_contacts_button, LV_OBJ_PART_MAIN);
|
||||
lv_obj_add_style(risk_contacts_button, LV_BTN_PART_MAIN, &yellow_button_style);
|
||||
} else {
|
||||
// Set Button red
|
||||
lv_obj_reset_style_list(risk_contacts_button, LV_OBJ_PART_MAIN);
|
||||
lv_obj_add_style(risk_contacts_button, LV_BTN_PART_MAIN, &red_button_style);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void display_thread(void* arg1, void* arg2, void* arg3) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
int init_styles() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update_display() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int init_display() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_message(char* msg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_time(int time) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_bat(int bat) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_mem(int mem) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_contacts(int contacts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int display_set_risk_contacts(int risk_contacts) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,208 +0,0 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "covid_types.h"
|
||||
#include "ens/ens_error.h"
|
||||
#include "ens/records.h"
|
||||
#include "ens/sequencenumber.h"
|
||||
#include "ens/storage.h"
|
||||
|
||||
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
||||
record_sequence_number_t* opt_start,
|
||||
record_sequence_number_t* opt_end) {
|
||||
// prevent any changes during initialization
|
||||
int rc = get_sequence_number_interval(&iterator->sn_next, &iterator->sn_end);
|
||||
if (rc == 0) {
|
||||
iterator->finished = false;
|
||||
|
||||
// we override start and end with the optional values
|
||||
if (opt_start) {
|
||||
iterator->sn_next = *opt_start;
|
||||
}
|
||||
if (opt_end) {
|
||||
iterator->sn_end = *opt_end;
|
||||
}
|
||||
} else {
|
||||
iterator->finished = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t get_timestamp_for_sn(record_sequence_number_t sn) {
|
||||
record_t rec;
|
||||
if (load_record(&rec, sn) == 0) {
|
||||
return rec.timestamp;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
enum record_timestamp_search_mode {
|
||||
RECORD_TIMESTAMP_SEARCH_MODE_MIN,
|
||||
RECORD_TIMESTAMP_SEARCH_MODE_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Find an entry via binary search for the timestamp.
|
||||
*
|
||||
* @param record pointer to the location, where the found sn shall be stored
|
||||
* @param target timestamp for which to find the nearest entry for
|
||||
* @param greater flag for indicating, if the loaded sn shall correspond to a greater (1) or smaller (0) timestamp
|
||||
*/
|
||||
int find_sn_via_binary_search(record_sequence_number_t* sn_dest,
|
||||
uint32_t target,
|
||||
enum record_timestamp_search_mode search_mode) {
|
||||
record_sequence_number_t start_sn;
|
||||
record_sequence_number_t end_sn;
|
||||
|
||||
// prevent any changes during binary search initialization
|
||||
|
||||
int rc = get_sequence_number_interval(&start_sn, &end_sn);
|
||||
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
record_sequence_number_t last_sn =
|
||||
start_sn; // used to check if ran into issues, e.g. could not load the entry or rounding errors
|
||||
|
||||
while (!sn_equal(start_sn, end_sn)) {
|
||||
// calculate the sn in the middle between start and end
|
||||
record_sequence_number_t cur_sn = sn_get_middle_sn(start_sn, end_sn);
|
||||
|
||||
if (sn_equal(cur_sn, last_sn)) {
|
||||
// if we already checked this entry -> we reduce our boundaries and try again
|
||||
// this also solves issues with rounding
|
||||
// TODO: This is not the best way...
|
||||
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
||||
int64_t start_ts = get_timestamp_for_sn(start_sn);
|
||||
if (start_ts == -1 || start_ts < target) {
|
||||
// we could not load this entry or this entry is strictly smaller than our target
|
||||
start_sn = sn_increment(start_sn); // we can safely increment as start_sn < end_sn
|
||||
} else {
|
||||
// we actually found the wanted entry!
|
||||
end_sn = start_sn; // this will break our loop
|
||||
}
|
||||
} else {
|
||||
// we search for the biggest value among them
|
||||
int64_t end_ts = get_timestamp_for_sn(end_sn);
|
||||
if (end_ts == -1 || end_ts > target) {
|
||||
// we could not load this entry or this entry is strictly bigger than our target
|
||||
end_sn = sn_decrement(end_sn); // we can safely decrement as start_sn < end_sn
|
||||
} else {
|
||||
// we actually found the wanted entry!
|
||||
start_sn = end_sn; // this will break our loop
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int64_t mid_ts = get_timestamp_for_sn(cur_sn);
|
||||
|
||||
if (mid_ts >= 0) {
|
||||
if (target < mid_ts) {
|
||||
end_sn = cur_sn;
|
||||
} else if (target > mid_ts) {
|
||||
start_sn = cur_sn;
|
||||
} else {
|
||||
// target == mid_ts
|
||||
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
||||
// we search for the smallest value among them -> look before this item
|
||||
end_sn = cur_sn;
|
||||
} else {
|
||||
// we search for the biggest value among them -> look after this item
|
||||
start_sn = cur_sn;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// some errors -> we keep the current sn and try to narrow our boundaries
|
||||
}
|
||||
}
|
||||
last_sn = cur_sn;
|
||||
}
|
||||
|
||||
*sn_dest = start_sn; // == end_sn
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: This iterator does neither check if the sequence numbers wrapped around while iteration. As a result, first
|
||||
// results could have later timestamps than following entries
|
||||
int ens_records_iterator_init_timerange(record_iterator_t* iterator, time_t* ts_start, time_t* ts_end) {
|
||||
record_sequence_number_t oldest_sn = 0;
|
||||
record_sequence_number_t newest_sn = 0;
|
||||
|
||||
// assure that *ts_end > *ts_start
|
||||
if (ts_start && ts_end && *ts_end < *ts_start) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ts_start) {
|
||||
int rc = find_sn_via_binary_search(&oldest_sn, *ts_start, RECORD_TIMESTAMP_SEARCH_MODE_MIN);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
oldest_sn = get_oldest_sequence_number();
|
||||
}
|
||||
|
||||
if (ts_end) {
|
||||
int rc = find_sn_via_binary_search(&newest_sn, *ts_end, RECORD_TIMESTAMP_SEARCH_MODE_MAX);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
newest_sn = get_latest_sequence_number();
|
||||
}
|
||||
|
||||
return ens_records_iterator_init_range(iterator, &oldest_sn, &newest_sn);
|
||||
}
|
||||
|
||||
record_t* ens_records_iterator_next(record_iterator_t* iter) {
|
||||
record_t* next = NULL;
|
||||
|
||||
while (next == NULL && !iter->finished) {
|
||||
record_t contact;
|
||||
// try to load the next contact
|
||||
int res = load_record(&contact, iter->sn_next);
|
||||
|
||||
if (!res) {
|
||||
next = &iter->current;
|
||||
memcpy(next, &contact, sizeof(record_t));
|
||||
}
|
||||
|
||||
if (sn_equal(iter->sn_next, iter->sn_end)) {
|
||||
iter->finished = true; // this iterator will finish after this execution
|
||||
} else {
|
||||
// increase the current sn
|
||||
iter->sn_next = sn_increment(iter->sn_next);
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
int ens_record_iterator_clear(record_iterator_t* iter) {
|
||||
// clear all relevant fields in the iterator
|
||||
iter->finished = true;
|
||||
iter->sn_next = 0;
|
||||
iter->sn_end = 0;
|
||||
memset(&iter->current, 0, sizeof(iter->current));
|
||||
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;
|
||||
}
|
@ -1,682 +0,0 @@
|
||||
/* Generated by the protocol buffer compiler. DO NOT EDIT! */
|
||||
/* Generated from: export.proto */
|
||||
|
||||
/* Do not generate deprecated warnings for self */
|
||||
#ifndef PROTOBUF_C__NO_DEPRECATED
|
||||
#define PROTOBUF_C__NO_DEPRECATED
|
||||
#endif
|
||||
|
||||
#include "export.pb-c.h"
|
||||
void temporary_exposure_key_export__init
|
||||
(TemporaryExposureKeyExport *message)
|
||||
{
|
||||
static const TemporaryExposureKeyExport init_value = TEMPORARY_EXPOSURE_KEY_EXPORT__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t temporary_exposure_key_export__get_packed_size
|
||||
(const TemporaryExposureKeyExport *message)
|
||||
{
|
||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t temporary_exposure_key_export__pack
|
||||
(const TemporaryExposureKeyExport *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t temporary_exposure_key_export__pack_to_buffer
|
||||
(const TemporaryExposureKeyExport *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
TemporaryExposureKeyExport *
|
||||
temporary_exposure_key_export__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (TemporaryExposureKeyExport *)
|
||||
protobuf_c_message_unpack (&temporary_exposure_key_export__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void temporary_exposure_key_export__free_unpacked
|
||||
(TemporaryExposureKeyExport *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &temporary_exposure_key_export__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void signature_info__init
|
||||
(SignatureInfo *message)
|
||||
{
|
||||
static const SignatureInfo init_value = SIGNATURE_INFO__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t signature_info__get_packed_size
|
||||
(const SignatureInfo *message)
|
||||
{
|
||||
assert(message->base.descriptor == &signature_info__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t signature_info__pack
|
||||
(const SignatureInfo *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &signature_info__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t signature_info__pack_to_buffer
|
||||
(const SignatureInfo *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &signature_info__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
SignatureInfo *
|
||||
signature_info__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (SignatureInfo *)
|
||||
protobuf_c_message_unpack (&signature_info__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void signature_info__free_unpacked
|
||||
(SignatureInfo *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &signature_info__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void temporary_exposure_key__init
|
||||
(TemporaryExposureKey *message)
|
||||
{
|
||||
static const TemporaryExposureKey init_value = TEMPORARY_EXPOSURE_KEY__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t temporary_exposure_key__get_packed_size
|
||||
(const TemporaryExposureKey *message)
|
||||
{
|
||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t temporary_exposure_key__pack
|
||||
(const TemporaryExposureKey *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t temporary_exposure_key__pack_to_buffer
|
||||
(const TemporaryExposureKey *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
TemporaryExposureKey *
|
||||
temporary_exposure_key__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (TemporaryExposureKey *)
|
||||
protobuf_c_message_unpack (&temporary_exposure_key__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void temporary_exposure_key__free_unpacked
|
||||
(TemporaryExposureKey *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &temporary_exposure_key__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void teksignature_list__init
|
||||
(TEKSignatureList *message)
|
||||
{
|
||||
static const TEKSignatureList init_value = TEKSIGNATURE_LIST__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t teksignature_list__get_packed_size
|
||||
(const TEKSignatureList *message)
|
||||
{
|
||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t teksignature_list__pack
|
||||
(const TEKSignatureList *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t teksignature_list__pack_to_buffer
|
||||
(const TEKSignatureList *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
TEKSignatureList *
|
||||
teksignature_list__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (TEKSignatureList *)
|
||||
protobuf_c_message_unpack (&teksignature_list__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void teksignature_list__free_unpacked
|
||||
(TEKSignatureList *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &teksignature_list__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
void teksignature__init
|
||||
(TEKSignature *message)
|
||||
{
|
||||
static const TEKSignature init_value = TEKSIGNATURE__INIT;
|
||||
*message = init_value;
|
||||
}
|
||||
size_t teksignature__get_packed_size
|
||||
(const TEKSignature *message)
|
||||
{
|
||||
assert(message->base.descriptor == &teksignature__descriptor);
|
||||
return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));
|
||||
}
|
||||
size_t teksignature__pack
|
||||
(const TEKSignature *message,
|
||||
uint8_t *out)
|
||||
{
|
||||
assert(message->base.descriptor == &teksignature__descriptor);
|
||||
return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);
|
||||
}
|
||||
size_t teksignature__pack_to_buffer
|
||||
(const TEKSignature *message,
|
||||
ProtobufCBuffer *buffer)
|
||||
{
|
||||
assert(message->base.descriptor == &teksignature__descriptor);
|
||||
return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);
|
||||
}
|
||||
TEKSignature *
|
||||
teksignature__unpack
|
||||
(ProtobufCAllocator *allocator,
|
||||
size_t len,
|
||||
const uint8_t *data)
|
||||
{
|
||||
return (TEKSignature *)
|
||||
protobuf_c_message_unpack (&teksignature__descriptor,
|
||||
allocator, len, data);
|
||||
}
|
||||
void teksignature__free_unpacked
|
||||
(TEKSignature *message,
|
||||
ProtobufCAllocator *allocator)
|
||||
{
|
||||
if(!message)
|
||||
return;
|
||||
assert(message->base.descriptor == &teksignature__descriptor);
|
||||
protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);
|
||||
}
|
||||
static const ProtobufCFieldDescriptor temporary_exposure_key_export__field_descriptors[8] =
|
||||
{
|
||||
{
|
||||
"start_timestamp",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_FIXED64,
|
||||
offsetof(TemporaryExposureKeyExport, has_start_timestamp),
|
||||
offsetof(TemporaryExposureKeyExport, start_timestamp),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"end_timestamp",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_FIXED64,
|
||||
offsetof(TemporaryExposureKeyExport, has_end_timestamp),
|
||||
offsetof(TemporaryExposureKeyExport, end_timestamp),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"region",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(TemporaryExposureKeyExport, region),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"batch_num",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TemporaryExposureKeyExport, has_batch_num),
|
||||
offsetof(TemporaryExposureKeyExport, batch_num),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"batch_size",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TemporaryExposureKeyExport, has_batch_size),
|
||||
offsetof(TemporaryExposureKeyExport, batch_size),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"signature_infos",
|
||||
6,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(TemporaryExposureKeyExport, n_signature_infos),
|
||||
offsetof(TemporaryExposureKeyExport, signature_infos),
|
||||
&signature_info__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"keys",
|
||||
7,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(TemporaryExposureKeyExport, n_keys),
|
||||
offsetof(TemporaryExposureKeyExport, keys),
|
||||
&temporary_exposure_key__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"revised_keys",
|
||||
8,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(TemporaryExposureKeyExport, n_revised_keys),
|
||||
offsetof(TemporaryExposureKeyExport, revised_keys),
|
||||
&temporary_exposure_key__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned temporary_exposure_key_export__field_indices_by_name[] = {
|
||||
3, /* field[3] = batch_num */
|
||||
4, /* field[4] = batch_size */
|
||||
1, /* field[1] = end_timestamp */
|
||||
6, /* field[6] = keys */
|
||||
2, /* field[2] = region */
|
||||
7, /* field[7] = revised_keys */
|
||||
5, /* field[5] = signature_infos */
|
||||
0, /* field[0] = start_timestamp */
|
||||
};
|
||||
static const ProtobufCIntRange temporary_exposure_key_export__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 8 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor temporary_exposure_key_export__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"TemporaryExposureKeyExport",
|
||||
"TemporaryExposureKeyExport",
|
||||
"TemporaryExposureKeyExport",
|
||||
"",
|
||||
sizeof(TemporaryExposureKeyExport),
|
||||
8,
|
||||
temporary_exposure_key_export__field_descriptors,
|
||||
temporary_exposure_key_export__field_indices_by_name,
|
||||
1, temporary_exposure_key_export__number_ranges,
|
||||
(ProtobufCMessageInit) temporary_exposure_key_export__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor signature_info__field_descriptors[3] =
|
||||
{
|
||||
{
|
||||
"verification_key_version",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(SignatureInfo, verification_key_version),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"verification_key_id",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(SignatureInfo, verification_key_id),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"signature_algorithm",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_STRING,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(SignatureInfo, signature_algorithm),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned signature_info__field_indices_by_name[] = {
|
||||
2, /* field[2] = signature_algorithm */
|
||||
1, /* field[1] = verification_key_id */
|
||||
0, /* field[0] = verification_key_version */
|
||||
};
|
||||
static const ProtobufCIntRange signature_info__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 3, 0 },
|
||||
{ 0, 3 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor signature_info__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"SignatureInfo",
|
||||
"SignatureInfo",
|
||||
"SignatureInfo",
|
||||
"",
|
||||
sizeof(SignatureInfo),
|
||||
3,
|
||||
signature_info__field_descriptors,
|
||||
signature_info__field_indices_by_name,
|
||||
1, signature_info__number_ranges,
|
||||
(ProtobufCMessageInit) signature_info__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCEnumValue temporary_exposure_key__report_type__enum_values_by_number[6] =
|
||||
{
|
||||
{ "UNKNOWN", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__UNKNOWN", 0 },
|
||||
{ "CONFIRMED_TEST", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_TEST", 1 },
|
||||
{ "CONFIRMED_CLINICAL_DIAGNOSIS", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__CONFIRMED_CLINICAL_DIAGNOSIS", 2 },
|
||||
{ "SELF_REPORT", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__SELF_REPORT", 3 },
|
||||
{ "RECURSIVE", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__RECURSIVE", 4 },
|
||||
{ "REVOKED", "TEMPORARY_EXPOSURE_KEY__REPORT_TYPE__REVOKED", 5 },
|
||||
};
|
||||
static const ProtobufCIntRange temporary_exposure_key__report_type__value_ranges[] = {
|
||||
{0, 0},{0, 6}
|
||||
};
|
||||
static const ProtobufCEnumValueIndex temporary_exposure_key__report_type__enum_values_by_name[6] =
|
||||
{
|
||||
{ "CONFIRMED_CLINICAL_DIAGNOSIS", 2 },
|
||||
{ "CONFIRMED_TEST", 1 },
|
||||
{ "RECURSIVE", 4 },
|
||||
{ "REVOKED", 5 },
|
||||
{ "SELF_REPORT", 3 },
|
||||
{ "UNKNOWN", 0 },
|
||||
};
|
||||
const ProtobufCEnumDescriptor temporary_exposure_key__report_type__descriptor =
|
||||
{
|
||||
PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC,
|
||||
"TemporaryExposureKey.ReportType",
|
||||
"ReportType",
|
||||
"TemporaryExposureKey__ReportType",
|
||||
"",
|
||||
6,
|
||||
temporary_exposure_key__report_type__enum_values_by_number,
|
||||
6,
|
||||
temporary_exposure_key__report_type__enum_values_by_name,
|
||||
1,
|
||||
temporary_exposure_key__report_type__value_ranges,
|
||||
NULL,NULL,NULL,NULL /* reserved[1234] */
|
||||
};
|
||||
static const int32_t temporary_exposure_key__rolling_period__default_value = 144;
|
||||
static const ProtobufCFieldDescriptor temporary_exposure_key__field_descriptors[6] =
|
||||
{
|
||||
{
|
||||
"key_data",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
offsetof(TemporaryExposureKey, has_key_data),
|
||||
offsetof(TemporaryExposureKey, key_data),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"transmission_risk_level",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TemporaryExposureKey, has_transmission_risk_level),
|
||||
offsetof(TemporaryExposureKey, transmission_risk_level),
|
||||
NULL,
|
||||
NULL,
|
||||
0 | PROTOBUF_C_FIELD_FLAG_DEPRECATED, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"rolling_start_interval_number",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TemporaryExposureKey, has_rolling_start_interval_number),
|
||||
offsetof(TemporaryExposureKey, rolling_start_interval_number),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"rolling_period",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TemporaryExposureKey, has_rolling_period),
|
||||
offsetof(TemporaryExposureKey, rolling_period),
|
||||
NULL,
|
||||
&temporary_exposure_key__rolling_period__default_value,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"report_type",
|
||||
5,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_ENUM,
|
||||
offsetof(TemporaryExposureKey, has_report_type),
|
||||
offsetof(TemporaryExposureKey, report_type),
|
||||
&temporary_exposure_key__report_type__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"days_since_onset_of_symptoms",
|
||||
6,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_SINT32,
|
||||
offsetof(TemporaryExposureKey, has_days_since_onset_of_symptoms),
|
||||
offsetof(TemporaryExposureKey, days_since_onset_of_symptoms),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned temporary_exposure_key__field_indices_by_name[] = {
|
||||
5, /* field[5] = days_since_onset_of_symptoms */
|
||||
0, /* field[0] = key_data */
|
||||
4, /* field[4] = report_type */
|
||||
3, /* field[3] = rolling_period */
|
||||
2, /* field[2] = rolling_start_interval_number */
|
||||
1, /* field[1] = transmission_risk_level */
|
||||
};
|
||||
static const ProtobufCIntRange temporary_exposure_key__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 6 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor temporary_exposure_key__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"TemporaryExposureKey",
|
||||
"TemporaryExposureKey",
|
||||
"TemporaryExposureKey",
|
||||
"",
|
||||
sizeof(TemporaryExposureKey),
|
||||
6,
|
||||
temporary_exposure_key__field_descriptors,
|
||||
temporary_exposure_key__field_indices_by_name,
|
||||
1, temporary_exposure_key__number_ranges,
|
||||
(ProtobufCMessageInit) temporary_exposure_key__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor teksignature_list__field_descriptors[1] =
|
||||
{
|
||||
{
|
||||
"signatures",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_REPEATED,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
offsetof(TEKSignatureList, n_signatures),
|
||||
offsetof(TEKSignatureList, signatures),
|
||||
&teksignature__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned teksignature_list__field_indices_by_name[] = {
|
||||
0, /* field[0] = signatures */
|
||||
};
|
||||
static const ProtobufCIntRange teksignature_list__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 1 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor teksignature_list__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"TEKSignatureList",
|
||||
"TEKSignatureList",
|
||||
"TEKSignatureList",
|
||||
"",
|
||||
sizeof(TEKSignatureList),
|
||||
1,
|
||||
teksignature_list__field_descriptors,
|
||||
teksignature_list__field_indices_by_name,
|
||||
1, teksignature_list__number_ranges,
|
||||
(ProtobufCMessageInit) teksignature_list__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
||||
static const ProtobufCFieldDescriptor teksignature__field_descriptors[4] =
|
||||
{
|
||||
{
|
||||
"signature_info",
|
||||
1,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_MESSAGE,
|
||||
0, /* quantifier_offset */
|
||||
offsetof(TEKSignature, signature_info),
|
||||
&signature_info__descriptor,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"batch_num",
|
||||
2,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TEKSignature, has_batch_num),
|
||||
offsetof(TEKSignature, batch_num),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"batch_size",
|
||||
3,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_INT32,
|
||||
offsetof(TEKSignature, has_batch_size),
|
||||
offsetof(TEKSignature, batch_size),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
{
|
||||
"signature",
|
||||
4,
|
||||
PROTOBUF_C_LABEL_OPTIONAL,
|
||||
PROTOBUF_C_TYPE_BYTES,
|
||||
offsetof(TEKSignature, has_signature),
|
||||
offsetof(TEKSignature, signature),
|
||||
NULL,
|
||||
NULL,
|
||||
0, /* flags */
|
||||
0,NULL,NULL /* reserved1,reserved2, etc */
|
||||
},
|
||||
};
|
||||
static const unsigned teksignature__field_indices_by_name[] = {
|
||||
1, /* field[1] = batch_num */
|
||||
2, /* field[2] = batch_size */
|
||||
3, /* field[3] = signature */
|
||||
0, /* field[0] = signature_info */
|
||||
};
|
||||
static const ProtobufCIntRange teksignature__number_ranges[1 + 1] =
|
||||
{
|
||||
{ 1, 0 },
|
||||
{ 0, 4 }
|
||||
};
|
||||
const ProtobufCMessageDescriptor teksignature__descriptor =
|
||||
{
|
||||
PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,
|
||||
"TEKSignature",
|
||||
"TEKSignature",
|
||||
"TEKSignature",
|
||||
"",
|
||||
sizeof(TEKSignature),
|
||||
4,
|
||||
teksignature__field_descriptors,
|
||||
teksignature__field_indices_by_name,
|
||||
1, teksignature__number_ranges,
|
||||
(ProtobufCMessageInit) teksignature__init,
|
||||
NULL,NULL,NULL /* reserved[123] */
|
||||
};
|
@ -1,115 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/printk.h>
|
||||
#include <timing/timing.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#include <protobuf-c.h>
|
||||
|
||||
#include "export.pb-c.h"
|
||||
#include "extract_keys.h"
|
||||
|
||||
#define KEY_SIZE 16
|
||||
|
||||
void process_key(TemporaryExposureKey* key) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
size_t generate_keys(uint8_t** buffer_pointer, int num_keys) {
|
||||
// Initialize the key export data structure
|
||||
TemporaryExposureKeyExport export = TEMPORARY_EXPOSURE_KEY_EXPORT__INIT;
|
||||
|
||||
TemporaryExposureKey** key_ptrs = (TemporaryExposureKey**)k_malloc(sizeof(TemporaryExposureKey*) * num_keys);
|
||||
if (key_ptrs == NULL) {
|
||||
printk("Could not allocate memory for pointers\n");
|
||||
return 0;
|
||||
}
|
||||
export.batch_num = 1;
|
||||
export.batch_size = 1;
|
||||
|
||||
// Initialize the keys and their data
|
||||
uint8_t key_data[KEY_SIZE];
|
||||
for (int i = 0; i < KEY_SIZE; i++) {
|
||||
key_data[i] = 0xFF;
|
||||
}
|
||||
TemporaryExposureKey key = TEMPORARY_EXPOSURE_KEY__INIT;
|
||||
key.key_data.data = key_data;
|
||||
key.key_data.len = KEY_SIZE;
|
||||
key.has_key_data = true;
|
||||
|
||||
// All pointers will point to the same key. The protocol buffer will still have n keys encoded
|
||||
for (int i = 0; i < num_keys; i++) {
|
||||
key_ptrs[i] = &key;
|
||||
}
|
||||
export.n_keys = num_keys;
|
||||
export.keys = key_ptrs;
|
||||
|
||||
// Check size allocate memory and pack the buffer
|
||||
size_t required_buffer = temporary_exposure_key_export__get_packed_size(&export);
|
||||
uint8_t* buffer = (uint8_t*) k_malloc(required_buffer);
|
||||
if (buffer == NULL) {
|
||||
printk("Could not allocate memory for buffer\n");
|
||||
return 0;
|
||||
}
|
||||
*buffer_pointer = buffer;
|
||||
if (buffer != NULL) {
|
||||
size_t buf_size = temporary_exposure_key_export__pack(&export, buffer);
|
||||
k_free(key_ptrs);
|
||||
return buf_size;
|
||||
} else {
|
||||
printk("Buffer too small to serialize %d keys. %d bytes necessary\n", num_keys, required_buffer);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int unpack_keys(uint8_t* buf, size_t buf_size) {
|
||||
// Unpack protocol buffer
|
||||
printk("Buf size: %d\n", buf_size);
|
||||
TemporaryExposureKeyExport* export = temporary_exposure_key_export__unpack(NULL, buf_size, buf);
|
||||
if (export == NULL) {
|
||||
printk("error unpacking incoming message\n");
|
||||
return -2;
|
||||
}
|
||||
|
||||
// Iterate over new keys
|
||||
for (int i = 0; i < export->n_keys; i++) {
|
||||
TemporaryExposureKey* key = export->keys[i];
|
||||
process_key(key);
|
||||
}
|
||||
|
||||
// Iterate over revised keys
|
||||
for (int i = 0; i < export->n_revised_keys; i++) {
|
||||
TemporaryExposureKey* key = export->revised_keys[i];
|
||||
process_key(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_unpacking(int num_keys) {
|
||||
// Prepare time measurement
|
||||
timing_t start_time, end_time;
|
||||
uint64_t total_cycles;
|
||||
uint64_t total_ns;
|
||||
|
||||
// Generate Buffer
|
||||
uint8_t* buffer;
|
||||
size_t buffer_size = generate_keys(&buffer, num_keys);
|
||||
|
||||
// Test unpacking
|
||||
timing_init();
|
||||
timing_start();
|
||||
if (buffer_size) {
|
||||
start_time = timing_counter_get();
|
||||
unpack_keys(buffer, buffer_size);
|
||||
end_time = timing_counter_get();
|
||||
}
|
||||
|
||||
// Calculate measurements
|
||||
total_cycles = timing_cycles_get(&start_time, &end_time);
|
||||
total_ns = timing_cycles_to_ns(total_cycles);
|
||||
printk("\nUnpacking %d keys took %lld us\n\n", num_keys, total_ns / 1000);
|
||||
timing_stop();
|
||||
|
||||
k_free(buffer);
|
||||
return 0;
|
||||
}
|
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/printk.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/uuid.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
|
||||
#include "covid.h"
|
||||
#include "contacts.h"
|
||||
|
||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||
|
||||
static const struct bt_data ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
/* My Service UUID (same as above) */
|
||||
BT_DATA_BYTES(BT_DATA_UUID128_ALL,
|
||||
0x06, 0x51, 0xC7, 0x9E, 0xAD, 0xA7, 0x42, 0xEA,
|
||||
0x98, 0x6A, 0x9F, 0x69, 0x79, 0x0D, 0x11, 0xF2),
|
||||
};
|
||||
|
||||
static void connected(struct bt_conn *conn, uint8_t err)
|
||||
{
|
||||
|
||||
if (err) {
|
||||
printk("Connection failed (err 0x%02x)\n", err);
|
||||
} else {
|
||||
printk("Connected\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
printk("Disconnected (reason 0x%02x)\n", reason);
|
||||
}
|
||||
|
||||
static struct bt_conn_cb conn_callbacks = {
|
||||
.connected = connected,
|
||||
.disconnected = disconnected,
|
||||
};
|
||||
|
||||
|
||||
static void auth_cancel(struct bt_conn *conn)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
printk("Pairing cancelled: %s\n", addr);
|
||||
}
|
||||
|
||||
static struct bt_conn_auth_cb auth_cb_display = {
|
||||
.cancel = auth_cancel,
|
||||
};
|
||||
|
||||
int init_gatt(void)
|
||||
{
|
||||
bt_conn_cb_register(&conn_callbacks);
|
||||
bt_conn_auth_cb_register(&auth_cb_display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if CONFIG_BT
|
||||
|
||||
int do_gatt(void){
|
||||
//printk("gatt start\n");
|
||||
int err;
|
||||
|
||||
err = bt_le_adv_start(BT_LE_ADV_CONN_NAME, ad, ARRAY_SIZE(ad), NULL, 0);
|
||||
if (err) {
|
||||
printk("Advertising failed to start (err %d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
k_sleep(K_SECONDS(1));
|
||||
|
||||
err = bt_le_adv_stop();
|
||||
if (err) {
|
||||
printk("Advertising failed to stop (err %d)\n", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
//printk("gatt end\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int do_gatt(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
189
src/io.c
189
src/io.c
@ -1,189 +0,0 @@
|
||||
/* io.c - Application main entry point */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <device.h>
|
||||
#include <drivers/gpio.h>
|
||||
|
||||
#include "covid.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* Devicetree helper macro which gets the 'flags' cell from a 'gpios'
|
||||
* property, or returns 0 if the property has no 'flags' cell.
|
||||
*/
|
||||
|
||||
#define FLAGS_OR_ZERO(node) \
|
||||
COND_CODE_1(DT_PHA_HAS_CELL(node, gpios, flags), \
|
||||
(DT_GPIO_FLAGS(node, gpios)), \
|
||||
(0))
|
||||
|
||||
/*
|
||||
* Get button configuration from the devicetree sw0 alias.
|
||||
*
|
||||
* At least a GPIO device and pin number must be provided. The 'flags'
|
||||
* cell is optional.
|
||||
*/
|
||||
|
||||
#ifndef NATIVE_POSIX
|
||||
//on my NRF board this is button 1
|
||||
#define SW0_NODE DT_ALIAS(sw0)
|
||||
|
||||
#if DT_NODE_HAS_STATUS(SW0_NODE, okay)
|
||||
#define SW0_GPIO_LABEL DT_GPIO_LABEL(SW0_NODE, gpios)
|
||||
#define SW0_GPIO_PIN DT_GPIO_PIN(SW0_NODE, gpios)
|
||||
#define SW0_GPIO_FLAGS (GPIO_INPUT | FLAGS_OR_ZERO(SW0_NODE))
|
||||
#else
|
||||
#error "Unsupported board: sw0 devicetree alias is not defined"
|
||||
#define SW0_GPIO_LABEL ""
|
||||
#define SW0_GPIO_PIN 0
|
||||
#define SW0_GPIO_FLAGS 0
|
||||
#endif
|
||||
|
||||
//on my NRF board this is button 2
|
||||
#define SW1_NODE DT_ALIAS(sw1)
|
||||
|
||||
#if DT_NODE_HAS_STATUS(SW1_NODE, okay)
|
||||
#define SW1_GPIO_LABEL DT_GPIO_LABEL(SW1_NODE, gpios)
|
||||
#define SW1_GPIO_PIN DT_GPIO_PIN(SW1_NODE, gpios)
|
||||
#define SW1_GPIO_FLAGS (GPIO_INPUT | FLAGS_OR_ZERO(SW1_NODE))
|
||||
#else
|
||||
#error "Unsupported board: sw1 devicetree alias is not defined"
|
||||
#define SW1_GPIO_LABEL ""
|
||||
#define SW1_GPIO_PIN 0
|
||||
#define SW1_GPIO_FLAGS 0
|
||||
#endif
|
||||
|
||||
/* The devicetree node identifier for the "led0" alias. */
|
||||
#define LED0_NODE DT_ALIAS(led0)
|
||||
|
||||
#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
|
||||
#define LED0 DT_GPIO_LABEL(LED0_NODE, gpios)
|
||||
#define PIN DT_GPIO_PIN(LED0_NODE, gpios)
|
||||
#if DT_PHA_HAS_CELL(LED0_NODE, gpios, flags)
|
||||
#define FLAGS DT_GPIO_FLAGS(LED0_NODE, gpios)
|
||||
#endif
|
||||
#else
|
||||
/* A build error here means your board isn't set up to blink an LED. */
|
||||
#error "Unsupported board: led0 devicetree alias is not defined"
|
||||
#define LED0 ""
|
||||
#define PIN 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef FLAGS
|
||||
#define FLAGS 0
|
||||
#endif
|
||||
|
||||
|
||||
static struct gpio_callback button_0_cb_data;
|
||||
static struct gpio_callback button_1_cb_data;
|
||||
|
||||
#ifndef NATIVE_POSIX
|
||||
|
||||
void button_0_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins){
|
||||
set_infection(true);
|
||||
gpio_pin_set(dev, PIN, (int)1);
|
||||
printk("Button 0 (=infected) pressed at %" PRIu32 "\n", k_cycle_get_32());
|
||||
}
|
||||
|
||||
void button_1_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins){
|
||||
set_infection(false);
|
||||
gpio_pin_set(dev, PIN, (int)0);
|
||||
printk("Button 1 (=healthy) pressed at %" PRIu32 "\n", k_cycle_get_32());
|
||||
}
|
||||
|
||||
int init_io(){
|
||||
struct device *button0, *button1;
|
||||
int err = 0;
|
||||
//struct device *led;
|
||||
|
||||
button0 = device_get_binding(SW0_GPIO_LABEL);
|
||||
if (button0 == NULL) {
|
||||
printk("Error: didn't find %s device\n", SW0_GPIO_LABEL);
|
||||
return -1;
|
||||
}
|
||||
button1 = device_get_binding(SW1_GPIO_LABEL);
|
||||
if (button1 == NULL) {
|
||||
printk("Error: didn't find %s device\n", SW1_GPIO_LABEL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure(button0, SW0_GPIO_PIN, SW0_GPIO_FLAGS);
|
||||
if (err != 0) {
|
||||
printk("Error %d: failed to configure %s pin %d\n",
|
||||
err, SW0_GPIO_LABEL, SW0_GPIO_PIN);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure(button1, SW1_GPIO_PIN, SW1_GPIO_FLAGS);
|
||||
if (err != 0) {
|
||||
printk("Error %d: failed to configure %s pin %d\n",
|
||||
err, SW1_GPIO_LABEL, SW1_GPIO_PIN);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
err = gpio_pin_interrupt_configure(button0,
|
||||
SW0_GPIO_PIN,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (err != 0) {
|
||||
printk("Error %d: failed to configure interrupt on %s pin %d\n",
|
||||
err, SW0_GPIO_LABEL, SW0_GPIO_PIN);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = gpio_pin_interrupt_configure(button1,
|
||||
SW1_GPIO_PIN,
|
||||
GPIO_INT_EDGE_TO_ACTIVE);
|
||||
if (err != 0) {
|
||||
printk("Error %d: failed to configure interrupt on %s pin %d\n",
|
||||
err, SW1_GPIO_LABEL, SW1_GPIO_PIN);
|
||||
return err;
|
||||
}
|
||||
|
||||
gpio_init_callback(&button_0_cb_data, button_0_pressed, BIT(SW0_GPIO_PIN));
|
||||
gpio_add_callback(button0, &button_0_cb_data);
|
||||
printk("Set up button at %s pin %d\n", SW0_GPIO_LABEL, SW0_GPIO_PIN);
|
||||
|
||||
gpio_init_callback(&button_1_cb_data, button_1_pressed, BIT(SW1_GPIO_PIN));
|
||||
gpio_add_callback(button1, &button_1_cb_data);
|
||||
printk("Set up button at %s pin %d\n", SW1_GPIO_LABEL, SW1_GPIO_PIN);
|
||||
|
||||
struct device *dev;
|
||||
dev = device_get_binding(LED0);
|
||||
if (dev == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
|
||||
if (err < 0) {
|
||||
printk("Error %d: failed to configure leds\n", err);
|
||||
return err;
|
||||
}
|
||||
//Turn LED 0 off
|
||||
gpio_pin_set(dev, PIN, (int)0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void button_0_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
void button_1_pressed(struct device *dev, struct gpio_callback *cb, uint32_t pins) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
int init_io(){
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
72
src/main.c
72
src/main.c
@ -6,62 +6,41 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr.h>
|
||||
|
||||
#include <bluetooth/hci.h>
|
||||
#include <random/rand32.h>
|
||||
#include <sys/printk.h>
|
||||
|
||||
#include "bloom.h"
|
||||
#include "contacts.h"
|
||||
#include "covid.h"
|
||||
#include "covid_types.h"
|
||||
#include "display.h"
|
||||
#include "ens/storage.h"
|
||||
#include "exposure-notification.h"
|
||||
#include "extract_keys.h"
|
||||
#include "gatt_service.h"
|
||||
#include "io.h"
|
||||
#include "record_storage.h"
|
||||
#include "tek_storage.h"
|
||||
#include "sync_service.h"
|
||||
#include "tracing.h"
|
||||
|
||||
void main(void) {
|
||||
#if CONFIG_TEST_UNPACK_KEYS
|
||||
for (int i = 0; i < CONFIG_TEST_UNPACK_KEYS_N; i++) {
|
||||
test_unpacking(1 << i);
|
||||
}
|
||||
#endif
|
||||
|
||||
int err = 0;
|
||||
printk("Starting Covid Contact Tracer\n");
|
||||
printk("Starting Contact-Tracing Wristband...\n");
|
||||
|
||||
// first init everything
|
||||
#ifndef NATIVE_POSIX
|
||||
// Use custom randomization as the mbdet_tls context initialization messes with the Zeyhr BLE stack.
|
||||
err = en_init(sys_csrand_get);
|
||||
if (err) {
|
||||
printk("Cyrpto init failed (err %d)\n", err);
|
||||
printk("Crypto init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_FLASH
|
||||
err = init_record_storage(false);
|
||||
err = record_storage_init(false);
|
||||
if (err) {
|
||||
printk("init storage failed (err %d)\n", err);
|
||||
printk("init record storage failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
err = init_contacts();
|
||||
err = tek_storage_init(false);
|
||||
if (err) {
|
||||
printk("init contacts failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = init_io();
|
||||
if (err) {
|
||||
printk("Button init failed (err %d)\n", err);
|
||||
printk("init key storage failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_BT
|
||||
/* Initialize the Bluetooth Subsystem */
|
||||
err = bt_enable(NULL);
|
||||
if (err) {
|
||||
@ -69,29 +48,24 @@ void main(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Bluetooth initialized\n");
|
||||
|
||||
err = init_gatt();
|
||||
/* Initialize the Tracing Subsystem */
|
||||
err = tracing_init();
|
||||
if (err) {
|
||||
printk("init gatt failed(err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = init_covid();
|
||||
if (err) {
|
||||
printk("init covid failed (err %d)\n", err);
|
||||
printk("Tracing init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("init display\n");
|
||||
err = init_display();
|
||||
/* Initialize the Gatt Subsystem */
|
||||
err = sync_service_init();
|
||||
if (err) {
|
||||
printk("init display failed (err %d)\n", err);
|
||||
printk("Sync Service init failed (err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
printk("Components initialized! Starting Tracing and Gatt...\n");
|
||||
|
||||
do {
|
||||
do_covid();
|
||||
do_gatt();
|
||||
tracing_run();
|
||||
sync_service_run();
|
||||
} while (1);
|
||||
}
|
@ -9,10 +9,10 @@
|
||||
#include <zephyr.h>
|
||||
#include <sys/printk.h>
|
||||
|
||||
|
||||
void main(void) {
|
||||
void main_test(void) {
|
||||
while(1) {
|
||||
|
||||
printk("Hello World!\n");
|
||||
k_msleep(1000);
|
||||
}
|
||||
}
|
||||
|
@ -6,11 +6,10 @@
|
||||
#include <storage/flash_map.h>
|
||||
#include <string.h>
|
||||
#include <zephyr.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "ens/ens_error.h"
|
||||
#include "ens/ens_fs.h"
|
||||
#include "ens/sequencenumber.h"
|
||||
#include "ens/storage.h"
|
||||
#include "utility/ens_fs.h"
|
||||
#include "record_storage.h"
|
||||
|
||||
#define STORED_CONTACTS_INFO_ID 0
|
||||
|
||||
@ -59,7 +58,7 @@ int save_storage_information() {
|
||||
return rc;
|
||||
}
|
||||
|
||||
int init_record_storage(bool clean) {
|
||||
int record_storage_init(bool clean) {
|
||||
int rc = 0;
|
||||
struct flash_pages_info info;
|
||||
// define the nvs file system
|
||||
@ -231,3 +230,207 @@ int get_sequence_number_interval(record_sequence_number_t* oldest, record_sequen
|
||||
uint32_t get_num_records() {
|
||||
return record_information.count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int ens_records_iterator_init_range(record_iterator_t* iterator,
|
||||
record_sequence_number_t* opt_start,
|
||||
record_sequence_number_t* opt_end) {
|
||||
// prevent any changes during initialization
|
||||
int rc = get_sequence_number_interval(&iterator->sn_next, &iterator->sn_end);
|
||||
if (rc == 0) {
|
||||
iterator->finished = false;
|
||||
|
||||
// we override start and end with the optional values
|
||||
if (opt_start) {
|
||||
iterator->sn_next = *opt_start;
|
||||
}
|
||||
if (opt_end) {
|
||||
iterator->sn_end = *opt_end;
|
||||
}
|
||||
} else {
|
||||
iterator->finished = true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int64_t get_timestamp_for_sn(record_sequence_number_t sn) {
|
||||
record_t rec;
|
||||
if (load_record(&rec, sn) == 0) {
|
||||
return rec.timestamp;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
enum record_timestamp_search_mode {
|
||||
RECORD_TIMESTAMP_SEARCH_MODE_MIN,
|
||||
RECORD_TIMESTAMP_SEARCH_MODE_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* Find an entry via binary search for the timestamp.
|
||||
*
|
||||
* @param record pointer to the location, where the found sn shall be stored
|
||||
* @param target timestamp for which to find the nearest entry for
|
||||
* @param greater flag for indicating, if the loaded sn shall correspond to a greater (1) or smaller (0) timestamp
|
||||
*/
|
||||
int find_sn_via_binary_search(record_sequence_number_t* sn_dest,
|
||||
uint32_t target,
|
||||
enum record_timestamp_search_mode search_mode) {
|
||||
record_sequence_number_t start_sn;
|
||||
record_sequence_number_t end_sn;
|
||||
|
||||
// prevent any changes during binary search initialization
|
||||
|
||||
int rc = get_sequence_number_interval(&start_sn, &end_sn);
|
||||
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
record_sequence_number_t last_sn =
|
||||
start_sn; // used to check if ran into issues, e.g. could not load the entry or rounding errors
|
||||
|
||||
while (!sn_equal(start_sn, end_sn)) {
|
||||
// calculate the sn in the middle between start and end
|
||||
record_sequence_number_t cur_sn = sn_get_middle_sn(start_sn, end_sn);
|
||||
|
||||
if (sn_equal(cur_sn, last_sn)) {
|
||||
// if we already checked this entry -> we reduce our boundaries and try again
|
||||
// this also solves issues with rounding
|
||||
// TODO: This is not the best way...
|
||||
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
||||
int64_t start_ts = get_timestamp_for_sn(start_sn);
|
||||
if (start_ts == -1 || start_ts < target) {
|
||||
// we could not load this entry or this entry is strictly smaller than our target
|
||||
start_sn = sn_increment(start_sn); // we can safely increment as start_sn < end_sn
|
||||
} else {
|
||||
// we actually found the wanted entry!
|
||||
end_sn = start_sn; // this will break our loop
|
||||
}
|
||||
} else {
|
||||
// we search for the biggest value among them
|
||||
int64_t end_ts = get_timestamp_for_sn(end_sn);
|
||||
if (end_ts == -1 || end_ts > target) {
|
||||
// we could not load this entry or this entry is strictly bigger than our target
|
||||
end_sn = sn_decrement(end_sn); // we can safely decrement as start_sn < end_sn
|
||||
} else {
|
||||
// we actually found the wanted entry!
|
||||
start_sn = end_sn; // this will break our loop
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int64_t mid_ts = get_timestamp_for_sn(cur_sn);
|
||||
|
||||
if (mid_ts >= 0) {
|
||||
if (target < mid_ts) {
|
||||
end_sn = cur_sn;
|
||||
} else if (target > mid_ts) {
|
||||
start_sn = cur_sn;
|
||||
} else {
|
||||
// target == mid_ts
|
||||
if (search_mode == RECORD_TIMESTAMP_SEARCH_MODE_MIN) {
|
||||
// we search for the smallest value among them -> look before this item
|
||||
end_sn = cur_sn;
|
||||
} else {
|
||||
// we search for the biggest value among them -> look after this item
|
||||
start_sn = cur_sn;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// some errors -> we keep the current sn and try to narrow our boundaries
|
||||
}
|
||||
}
|
||||
last_sn = cur_sn;
|
||||
}
|
||||
|
||||
*sn_dest = start_sn; // == end_sn
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: This iterator does neither check if the sequence numbers wrapped around while iteration. As a result, first
|
||||
// results could have later timestamps than following entries
|
||||
int ens_records_iterator_init_timerange(record_iterator_t* iterator, time_t* ts_start, time_t* ts_end) {
|
||||
record_sequence_number_t oldest_sn = 0;
|
||||
record_sequence_number_t newest_sn = 0;
|
||||
|
||||
// assure that *ts_end > *ts_start
|
||||
if (ts_start && ts_end && *ts_end < *ts_start) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ts_start) {
|
||||
int rc = find_sn_via_binary_search(&oldest_sn, *ts_start, RECORD_TIMESTAMP_SEARCH_MODE_MIN);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
oldest_sn = get_oldest_sequence_number();
|
||||
}
|
||||
|
||||
if (ts_end) {
|
||||
int rc = find_sn_via_binary_search(&newest_sn, *ts_end, RECORD_TIMESTAMP_SEARCH_MODE_MAX);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
} else {
|
||||
newest_sn = get_latest_sequence_number();
|
||||
}
|
||||
|
||||
return ens_records_iterator_init_range(iterator, &oldest_sn, &newest_sn);
|
||||
}
|
||||
|
||||
record_t* ens_records_iterator_next(record_iterator_t* iter) {
|
||||
record_t* next = NULL;
|
||||
|
||||
while (next == NULL && !iter->finished) {
|
||||
record_t contact;
|
||||
// try to load the next contact
|
||||
int res = load_record(&contact, iter->sn_next);
|
||||
|
||||
if (!res) {
|
||||
next = &iter->current;
|
||||
memcpy(next, &contact, sizeof(record_t));
|
||||
}
|
||||
|
||||
if (sn_equal(iter->sn_next, iter->sn_end)) {
|
||||
iter->finished = true; // this iterator will finish after this execution
|
||||
} else {
|
||||
// increase the current sn
|
||||
iter->sn_next = sn_increment(iter->sn_next);
|
||||
}
|
||||
}
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
int ens_record_iterator_clear(record_iterator_t* iter) {
|
||||
// clear all relevant fields in the iterator
|
||||
iter->finished = true;
|
||||
iter->sn_next = 0;
|
||||
iter->sn_end = 0;
|
||||
memset(&iter->current, 0, sizeof(iter->current));
|
||||
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;
|
||||
}
|
27
src/sync_service.c
Normal file
27
src/sync_service.c
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2020 Olaf Landsiedel
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <sys/printk.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <zephyr.h>
|
||||
|
||||
#include <bluetooth/bluetooth.h>
|
||||
#include <bluetooth/conn.h>
|
||||
#include <bluetooth/uuid.h>
|
||||
#include <bluetooth/gatt.h>
|
||||
|
||||
|
||||
int sync_service_init(void) {
|
||||
return 0; // TODO!
|
||||
}
|
||||
|
||||
int sync_service_run(void) {
|
||||
return 0;
|
||||
}
|
26
src/tek_storage.c
Normal file
26
src/tek_storage.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include <string.h>
|
||||
#include "tek_storage.h"
|
||||
|
||||
int tek_storage_init(bool clean) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tek_storage_add(tek_t* src) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tek_storage_delete(tek_t* src) {
|
||||
// TODO
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 0 on success, else non zero (if none available)
|
||||
* TODO: This is not really implemented...
|
||||
*/
|
||||
int tek_storage_get_latest_at_ts(tek_t* dest, uint32_t timestamp) {
|
||||
dest->timestamp = timestamp;
|
||||
memset(&dest->tek, 0, sizeof(dest->tek));
|
||||
return 0;
|
||||
}
|
@ -15,21 +15,29 @@
|
||||
#include <kernel.h>
|
||||
|
||||
#include "exposure-notification.h"
|
||||
#include "covid_types.h"
|
||||
#include "contacts.h"
|
||||
#include "covid.h"
|
||||
#include "ens/storage.h"
|
||||
#include "tracing.h"
|
||||
#include "record_storage.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "utility/util.h"
|
||||
|
||||
#define COVID_ENS (0xFD6F)
|
||||
|
||||
typedef ENIntervalIdentifier ENIntervalIdentifier;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
typedef struct period{
|
||||
ENPeriodKey periodKey;
|
||||
ENIntervalNumber periodInterval;
|
||||
} __packed period_t;
|
||||
|
||||
#ifndef COVID_MEASURE_PERFORMANCE
|
||||
#define COVID_MEASURE_PERFORMANCE 0
|
||||
#endif
|
||||
|
||||
typedef struct covid_adv_svd
|
||||
{
|
||||
uint16_t ens;
|
||||
rolling_proximity_identifier_t rolling_proximity_identifier;
|
||||
ENIntervalIdentifier rolling_proximity_identifier;
|
||||
associated_encrypted_metadata_t associated_encrypted_metadata;
|
||||
} __packed covid_adv_svd_t;
|
||||
|
||||
@ -40,8 +48,6 @@ const static bt_metadata_t bt_metadata = {
|
||||
.rsv2 = 0,
|
||||
};
|
||||
|
||||
#define COVID_ENS (0xFD6F)
|
||||
|
||||
static covid_adv_svd_t covid_adv_svd = {
|
||||
.ens = COVID_ENS,
|
||||
//do not initialiuze the rest of the packet, will write this later
|
||||
@ -80,15 +86,15 @@ static void scan_cb(const bt_addr_le_t *addr, int8_t rssi, uint8_t adv_type, str
|
||||
covid_adv_svd_t *rx_adv = (covid_adv_svd_t *)buf->data;
|
||||
if (rx_adv->ens == COVID_ENS)
|
||||
{
|
||||
printk("Attempting to store contact...\n");
|
||||
record_t contact;
|
||||
printk("Attempting to store record...\n");
|
||||
record_t record;
|
||||
uint32_t timestamp = time_get_unix_seconds();
|
||||
memcpy(&contact.rssi, &rssi, sizeof(contact.rssi));
|
||||
memcpy(&contact.associated_encrypted_metadata, &rx_adv->associated_encrypted_metadata, sizeof(contact.associated_encrypted_metadata));
|
||||
memcpy(&contact.rolling_proximity_identifier, &rx_adv->rolling_proximity_identifier, sizeof(contact.rolling_proximity_identifier));
|
||||
memcpy(&contact.timestamp, ×tamp, sizeof(contact.timestamp));
|
||||
int rc = register_record(&contact);
|
||||
printk("Contact stored (err %d)\n", rc);
|
||||
memcpy(&record.rssi, &rssi, sizeof(record.rssi));
|
||||
memcpy(&record.associated_encrypted_metadata, &rx_adv->associated_encrypted_metadata, sizeof(record.associated_encrypted_metadata));
|
||||
memcpy(&record.rolling_proximity_identifier, &rx_adv->rolling_proximity_identifier, sizeof(record.rolling_proximity_identifier));
|
||||
memcpy(&record.timestamp, ×tamp, sizeof(record.timestamp));
|
||||
int rc = add_record(&record);
|
||||
printk("Record stored (err %d)\n", rc);
|
||||
}
|
||||
}
|
||||
net_buf_simple_pull(buf, len - 1); //consume the rest, note we already consumed one byte via net_buf_simple_pull_u8(buf)
|
||||
@ -167,120 +173,6 @@ static void new_period_key(time_t currentTime)
|
||||
#endif
|
||||
}
|
||||
|
||||
#if COVID_MEASURE_PERFORMANCE
|
||||
static void measure_performance()
|
||||
{
|
||||
|
||||
u32_t runs = 100;
|
||||
u32_t start_time;
|
||||
u32_t cycles_spent;
|
||||
u32_t nanoseconds_spent;
|
||||
|
||||
ENPeriodKey pk;
|
||||
|
||||
ENPeriodIdentifierKey pik;
|
||||
ENIntervalIdentifier intervalIdentifier;
|
||||
ENIntervalNumber intervalNumber = 2642976;
|
||||
ENIntervalIdentifier id;
|
||||
ENPeriodMetadataEncryptionKey pmek;
|
||||
unsigned char metadata[4] = {0x40, 0x08, 0x00, 0x00};
|
||||
unsigned char encryptedMetadata[sizeof(metadata)] = {0};
|
||||
|
||||
printk("\n----------------------------------------\n");
|
||||
printk("MEASURING PERFORMANCE\n");
|
||||
|
||||
// Measure en_generate_period_key
|
||||
{
|
||||
start_time = k_cycle_get_32();
|
||||
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
en_generate_period_key(&pk);
|
||||
}
|
||||
|
||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
||||
printk("en_generate_period_key %d ns\n", nanoseconds_spent/runs);
|
||||
}
|
||||
|
||||
// Measure en_derive_period_identifier_key
|
||||
{
|
||||
start_time = k_cycle_get_32();
|
||||
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
en_derive_period_identifier_key(&pik, &pk);
|
||||
}
|
||||
|
||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
||||
printk("en_derive_period_identifier_key %d ns\n", nanoseconds_spent/runs);
|
||||
}
|
||||
|
||||
// Measure en_derive_interval_identifier
|
||||
{
|
||||
start_time = k_cycle_get_32();
|
||||
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
en_derive_interval_identifier(&intervalIdentifier, &pik, intervalNumber);
|
||||
}
|
||||
|
||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
||||
printk("en_derive_interval_identifier %d ns\n", nanoseconds_spent/runs);
|
||||
}
|
||||
|
||||
// Measure en_derive_period_metadata_encryption_key
|
||||
{
|
||||
start_time = k_cycle_get_32();
|
||||
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
en_derive_period_metadata_encryption_key(&pmek, &pk);
|
||||
}
|
||||
|
||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
||||
printk("en_derive_period_metadata_encryption_key %d ns\n", nanoseconds_spent/runs);
|
||||
}
|
||||
|
||||
// Measure en_encrypt_interval_metadata
|
||||
{
|
||||
start_time = k_cycle_get_32();
|
||||
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
en_encrypt_interval_metadata(&pmek, &intervalIdentifier, metadata, encryptedMetadata, sizeof(metadata));
|
||||
}
|
||||
|
||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
||||
printk("en_encrypt_interval_metadata %d ns\n", nanoseconds_spent/runs);
|
||||
}
|
||||
|
||||
// Measure Full key generation
|
||||
{
|
||||
start_time = k_cycle_get_32();
|
||||
|
||||
for (int i = 0; i < runs; i++)
|
||||
{
|
||||
ENPeriodKey pk;
|
||||
en_generate_period_key(&pk);
|
||||
ENPeriodIdentifierKey ik;
|
||||
en_derive_period_identifier_key(&ik, &pk);
|
||||
|
||||
for(int iv = 0; iv < EN_TEK_ROLLING_PERIOD; iv++) {
|
||||
ENIntervalNumber intervalNumber = en_get_interval_number(iv);
|
||||
ENIntervalIdentifier id;
|
||||
en_derive_interval_identifier(&id, &ik, intervalNumber);
|
||||
}
|
||||
}
|
||||
|
||||
nanoseconds_spent = SYS_CLOCK_HW_CYCLES_TO_NS(k_cycle_get_32() - start_time);
|
||||
printk("Full key generation %d ns\n", nanoseconds_spent/runs);
|
||||
}
|
||||
|
||||
printk("\FINISHED\n");
|
||||
printk("----------------------------------------\n\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
//To be called when new keys are needed
|
||||
static void check_keys(struct k_work *work)
|
||||
{
|
||||
@ -314,10 +206,10 @@ static void check_keys(struct k_work *work)
|
||||
printk("Time: %u, ", currentTime);
|
||||
printk("Interval: %u, ", currentInterval);
|
||||
printk("TEK: ");
|
||||
print_rpi((rolling_proximity_identifier_t *)&periods[current_period_index].periodKey);
|
||||
print_rpi((ENIntervalIdentifier *)&periods[current_period_index].periodKey);
|
||||
printk(", ");
|
||||
printk("RPI: ");
|
||||
print_rpi((rolling_proximity_identifier_t *)&intervalIdentifier);
|
||||
print_rpi((ENIntervalIdentifier *)&intervalIdentifier);
|
||||
printk(", ");
|
||||
printk("AEM: ");
|
||||
print_aem(&encryptedMetadata);
|
||||
@ -325,7 +217,7 @@ static void check_keys(struct k_work *work)
|
||||
|
||||
// lock, so we can be sure to only advertise correct packages
|
||||
k_mutex_lock(&key_change_lock, K_FOREVER);
|
||||
memcpy(&covid_adv_svd.rolling_proximity_identifier, &intervalIdentifier, sizeof(rolling_proximity_identifier_t));
|
||||
memcpy(&covid_adv_svd.rolling_proximity_identifier, &intervalIdentifier, sizeof(ENIntervalIdentifier));
|
||||
memcpy(&covid_adv_svd.associated_encrypted_metadata, &encryptedMetadata, sizeof(associated_encrypted_metadata_t));
|
||||
k_mutex_unlock(&key_change_lock);
|
||||
|
||||
@ -351,7 +243,7 @@ static const struct bt_le_scan_param scan_param = {
|
||||
|
||||
#define KEY_CHECK_INTERVAL (K_MSEC(EN_INTERVAL_LENGTH * 1000 / 10))
|
||||
|
||||
int init_covid()
|
||||
int tracing_init()
|
||||
{
|
||||
|
||||
#if COVID_MEASURE_PERFORMANCE
|
||||
@ -383,7 +275,7 @@ int init_covid()
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_covid()
|
||||
int tracing_run()
|
||||
{
|
||||
//printk("covid start\n");
|
||||
|
||||
@ -445,17 +337,3 @@ period_t *get_period_if_infected(unsigned int id, size_t *size)
|
||||
*size = sizeof(period_t);
|
||||
return &periods[id];
|
||||
}
|
||||
|
||||
int get_index_by_interval(ENIntervalNumber periodInterval)
|
||||
{
|
||||
int index = 0;
|
||||
while (index < NUM_PERIOD_KEYS || index < period_cnt)
|
||||
{
|
||||
if (periods[index].periodInterval == periodInterval)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#include "time.h"
|
||||
#include <zephyr.h>
|
||||
// TODO: this is very basic atm
|
||||
uint32_t time_get_unix_seconds() {
|
||||
return k_uptime_get() / 1000;
|
||||
}
|
@ -6,8 +6,7 @@
|
||||
#include <string.h>
|
||||
#include <sys/crc.h>
|
||||
|
||||
#include "ens/ens_error.h"
|
||||
#include "ens/ens_fs.h"
|
||||
#include "utility/ens_fs.h"
|
||||
|
||||
#define SEED 42
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "ens/sequencenumber.h"
|
||||
#include "utility/sequencenumber.h"
|
||||
|
||||
#define SN_MASK 0xffffff
|
||||
|
27
src/utility/util.c
Normal file
27
src/utility/util.c
Normal file
@ -0,0 +1,27 @@
|
||||
#include "time.h"
|
||||
#include <zephyr.h>
|
||||
#include "utility/util.h"
|
||||
|
||||
|
||||
// TODO: this is very basic atm
|
||||
uint32_t time_get_unix_seconds() {
|
||||
return k_uptime_get() / 1000;
|
||||
}
|
||||
|
||||
void print_key(_ENBaseKey* key) {
|
||||
for (int i = 0; i < sizeof(key->b); i++) {
|
||||
printk("%02x", key->b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_rpi(ENIntervalIdentifier* rpi) {
|
||||
for (int i = 0; i < sizeof(ENIntervalIdentifier); i++) {
|
||||
printk("%02x", rpi->b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void print_aem(associated_encrypted_metadata_t* aem) {
|
||||
for (int i = 0; i < sizeof(associated_encrypted_metadata_t); i++) {
|
||||
printk("%02x", aem->data[i]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user