update to support ena-eke-proxy

This commit is contained in:
Lurkars
2020-12-06 12:46:36 +01:00
parent 8b38bde332
commit 9d0703aa62
28 changed files with 656 additions and 4771 deletions
+11
View File
@@ -0,0 +1,11 @@
idf_component_register(
SRCS
"ena-eke-proxy.c"
INCLUDE_DIRS "."
PRIV_REQUIRES
esp_http_client
ena
wifi-controller
EMBED_FILES
"certs/cert.pem"
)
@@ -0,0 +1,51 @@
menu "ENA Exposue Key Export Proxy"
config ENA_EKE_PROXY_KEYFILES_DAILY_URL
string "Url to fetch daily keys"
default "https://cwa-proxy.champonthis.de/version/v1/diagnosis-keys/country/DE/date/%s?page=%u&size=%u"
help
Defines the url to fetch keys. Datestring of ENA_EKE_PROXY_KEYFILES_DAILY_FORMAT (%s), page (%u) and size (%u) are passed as paramter. (Default https://cwa-proxy.champonthis.de/version/v1/diagnosis-keys/country/DE/date/%s?page=%u&size=%u)
config ENA_EKE_PROXY_KEYFILES_HOURLY
bool "Also fetch keys hourly"
default true
help
If enabled, the hourly keys will be fetched for current day.
config ENA_EKE_PROXY_KEYFILES_HOURLY_URL
string "Url to fetch daily keys"
depends on ENA_EKE_PROXY_KEYFILES_HOURLY
default "https://cwa-proxy.champonthis.de/version/v1/diagnosis-keys/country/DE/date/%s/hour/%u?page=%u&size=%u"
help
Defines the url to fetch keys. Datestring of ENA_EKE_PROXY_KEYFILES_DAILY_FORMAT (%s), hour (%u), page (%u) and size (%u) are passed as paramter. (Default https://cwa-proxy.champonthis.de/version/v1/diagnosis-keys/country/DE/date/%s/hour/%u?page=%u&size=%u)
config ENA_EKE_PROXY_KEYFILES_DAILY_FORMAT
string "Format of date to fetch"
default "%Y-%m-%d"
help
Defines the Datestring (%s) for setting the date in fetch url. (Default %Y-%m-%d)
config ENA_EKE_PROXY_KEYFILES_UPLOAD_URL
string "Url to upload keys"
default "https://cwa-proxy.champonthis.de/version/v1/diagnosis-keys"
help
Defines the url to upload keys to. (Default https://cwa-proxy.champonthis.de/version/v1/diagnosis-keys)
config ENA_EKE_PROXY_KEY_LIMIT
int "Limit of keys to receive"
default 500
help
Defines the limit of keys to receive in one request from server. (Default 500)
config ENA_EKE_PROXY_MAX_PAST_DAYS
int "Max. days to retrieve keys"
default 14
help
Defines the maximum number of days to receive missed keys from server. (Default 14)
config ENA_EKE_PROXY_AUTHORIZATION
string "Authorization Header value (PanTra)"
help
Defines the value to put in Authorization header during key upload. (For PanTra key server)
endmenu
+3
View File
@@ -0,0 +1,3 @@
-----BEGIN CERTIFICATE-----
MIIEkjCCA3qgAwIBAgIQCgFBQgAAAVOFc2oLheynCDANBgkqhkiG9w0BAQsFADA/MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4XDTE2MDMxNzE2NDA0NloXDTIxMDMxNzE2NDA0NlowSjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUxldCdzIEVuY3J5cHQxIzAhBgNVBAMTGkxldCdzIEVuY3J5cHQgQXV0aG9yaXR5IFgzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnNMM8FrlLke3cl03g7NoYzDq1zUmGSXhvb418XCSL7e4S0EFq6meNQhY7LEqxGiHC6PjdeTm86dicbp5gWAf15Gan/PQeGdxyGkOlZHP/uaZ6WA8SMx+yk13EiSdRxta67nsHjcAHJyse6cF6s5K671B5TaYucv9bTyWaN8jKkKQDIZ0Z8h/pZq4UmEUEz9l6YKHy9v6Dlb2honzhT+Xhq+w3Brvaw2VFn3EK6BlspkENnWAa6xK8xuQSXgvopZPKiAlKQTGdMDQMc2PMTiVFrqoM7hD8bEfwzB/onkxEz0tNvjj/PIzark5McWvxI0NHWQWM6r6hCm21AvA2H3DkwIDAQABo4IBfTCCAXkwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwfwYIKwYBBQUHAQEEczBxMDIGCCsGAQUFBzABhiZodHRwOi8vaXNyZy50cnVzdGlkLm9jc3AuaWRlbnRydXN0LmNvbTA7BggrBgEFBQcwAoYvaHR0cDovL2FwcHMuaWRlbnRydXN0LmNvbS9yb290cy9kc3Ryb290Y2F4My5wN2MwHwYDVR0jBBgwFoAUxKexpHsscfrb4UuQdf/EFWCFiRAwVAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcCARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vY3JsLmlkZW50cnVzdC5jb20vRFNUUk9PVENBWDNDUkwuY3JsMB0GA1UdDgQWBBSoSmpjBH3duubRObemRWXv86jsoTANBgkqhkiG9w0BAQsFAAOCAQEA3TPXEfNjWDjdGBX7CVW+dla5cEilaUcne8IkCJLxWh9KEik3JHRRHGJouM2VcGfl96S8TihRzZvoroed6ti6WqEBmtzw3Wodatg+VyOeph4EYpr/1wXKtx8/wApIvJSwtmVi4MFU5aMqrSDE6ea73Mj2tcMyo5jMd6jmeWUHK8so/joWUoHOUgwuX4Po1QYz+3dszkDqMp4fklxBwXRsW10KXzPMTZ+sOPAveyxindmjkW8lGy+QsRlGPfZ+G6Z6h7mjem0Y+iWlkYcV4PIWL1iwBi8saCbGS5jN2p8M+X+Q7UNKEkROb3N6KOqkqm57TH2H3eDJAkSnh6/DNFu0Qg==
-----END CERTIFICATE-----
+401
View File
@@ -0,0 +1,401 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string.h>
#include "time.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_http_client.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ena-crypto.h"
#include "ena-storage.h"
#include "ena-exposure.h"
#include "wifi-controller.h"
#include "ena-eke-proxy.h"
#define HOUR_IN_SECONDS (60 * 60)
#define DAY_IN_SECONDS (HOUR_IN_SECONDS * 24)
extern const uint8_t cert_pem_start[] asm("_binary_cert_pem_start");
extern const uint8_t cert_pem_end[] asm("_binary_cert_pem_end");
static size_t current_page = 0;
static time_t request_sleep = 0;
static uint32_t request_sleep_waiting = 30;
static time_t last_check = 0;
static bool wait_for_request = false;
esp_err_t ena_eke_proxy_fetch_event_handler(esp_http_client_event_t *evt)
{
static uint8_t *output_buffer;
static int output_len;
switch (evt->event_id)
{
case HTTP_EVENT_ON_DATA:
if (!esp_http_client_is_chunked_response(evt->client))
{
if (output_buffer == NULL)
{
output_buffer = malloc(esp_http_client_get_content_length(evt->client));
output_len = 0;
if (output_buffer == NULL)
{
ESP_LOGE(ENA_EKE_PROXY_LOG, "Failed to allocate memory for output buffer, memory: %d kB", (xPortGetFreeHeapSize() / 1024));
return ESP_FAIL;
}
}
memcpy(output_buffer + output_len, evt->data, evt->data_len);
output_len += evt->data_len;
}
break;
case HTTP_EVENT_ON_FINISH:
if (output_buffer != NULL && esp_http_client_get_status_code(evt->client) == 200)
{
if (output_len % 28 != 0)
{
ESP_LOGW(ENA_EKE_PROXY_LOG, "Response length does not match key size! %d", output_len);
}
size_t temporary_exposure_keys = (output_len / 28);
if (temporary_exposure_keys > 0)
{
uint32_t start_time = (uint32_t)time(NULL);
ena_temporary_exposure_key_t temporary_exposure_key;
int tek_index = 0;
memcpy(&(temporary_exposure_key.key_data), &output_buffer[tek_index * 28], ENA_KEY_LENGTH);
memcpy(&(temporary_exposure_key.rolling_start_interval_number), &output_buffer[tek_index * 28 + ENA_KEY_LENGTH], 4);
memcpy(&(temporary_exposure_key.rolling_period), &output_buffer[tek_index * 28 + ENA_KEY_LENGTH + 4], 4);
memcpy(&(temporary_exposure_key.days_since_onset_of_symptoms), &output_buffer[tek_index * 28 + ENA_KEY_LENGTH + 8], 4);
uint32_t timestamp_start = temporary_exposure_key.rolling_start_interval_number * ENA_TIME_WINDOW;
int min = ena_expore_check_find_min(timestamp_start);
tek_index = temporary_exposure_keys - 1;
memcpy(&(temporary_exposure_key.key_data), &output_buffer[tek_index * 28], ENA_KEY_LENGTH);
memcpy(&(temporary_exposure_key.rolling_start_interval_number), &output_buffer[tek_index * 28 + ENA_KEY_LENGTH], 4);
memcpy(&(temporary_exposure_key.rolling_period), &output_buffer[tek_index * 28 + ENA_KEY_LENGTH + 4], 4);
memcpy(&(temporary_exposure_key.days_since_onset_of_symptoms), &output_buffer[tek_index * 28 + ENA_KEY_LENGTH + 8], 4);
uint32_t timestamp_end = (temporary_exposure_key.rolling_start_interval_number + temporary_exposure_key.rolling_period) * ENA_TIME_WINDOW;
int max = ena_expore_check_find_max(timestamp_end);
if (min >= 0 && max >= 0 && min <= max)
{
ESP_LOGI(ENA_EKE_PROXY_LOG, "start check with beacons [%d,%d] for [%u,%u]", min, max, timestamp_start, timestamp_end);
ena_beacon_t beacon;
for (int y = min; y <= max; y++)
{
ena_storage_get_beacon(y, &beacon);
for (int i = 0; i < temporary_exposure_keys; i++)
{
memcpy(&(temporary_exposure_key.key_data), &output_buffer[i * 28], ENA_KEY_LENGTH);
memcpy(&(temporary_exposure_key.rolling_start_interval_number), &output_buffer[i * 28 + ENA_KEY_LENGTH], 4);
memcpy(&(temporary_exposure_key.rolling_period), &output_buffer[i * 28 + ENA_KEY_LENGTH + 4], 4);
memcpy(&(temporary_exposure_key.days_since_onset_of_symptoms), &output_buffer[i * 28 + ENA_KEY_LENGTH + 8], 4);
#ifdef DEBUG_ENA_EKE_PROXY
ESP_LOGD(ENA_EKE_PROXY_LOG, "key payload: ");
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, &output_buffer[i * 28], 28, ESP_LOG_DEBUG);
ESP_LOGD(ENA_EKE_PROXY_LOG, "received key: ");
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, &(temporary_exposure_key.key_data), ENA_KEY_LENGTH, ESP_LOG_DEBUG);
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, &output_buffer[i * 28], ENA_KEY_LENGTH, ESP_LOG_DEBUG);
ESP_LOGD(ENA_EKE_PROXY_LOG, "rolling_start_interval_number %u", temporary_exposure_key.rolling_start_interval_number);
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, &output_buffer[i * 28 + ENA_KEY_LENGTH], 4, ESP_LOG_DEBUG);
ESP_LOGD(ENA_EKE_PROXY_LOG, "rolling_period %u", temporary_exposure_key.rolling_period);
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, &output_buffer[i * 28 + ENA_KEY_LENGTH + 4], 4, ESP_LOG_DEBUG);
ESP_LOGD(ENA_EKE_PROXY_LOG, "days_since_onset_of_symptoms %u", temporary_exposure_key.days_since_onset_of_symptoms);
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, &output_buffer[i * 28 + ENA_KEY_LENGTH + 8], 4, ESP_LOG_DEBUG);
#endif
ena_exposure_check(beacon, temporary_exposure_key);
}
}
uint32_t end_time = (uint32_t)time(NULL);
ESP_LOGI(ENA_EKE_PROXY_LOG, "check took %u seconds", (end_time - start_time));
}
else
{
ESP_LOGD(ENA_EKE_PROXY_LOG, "no matching beacons for [%u,%u]", timestamp_start, timestamp_end);
}
}
else
{
ESP_LOGW(ENA_EKE_PROXY_LOG, "no keys in request, should not happen on 200 status!");
}
current_page = current_page + 1;
free(output_buffer);
}
else if (esp_http_client_get_status_code(evt->client) == 204)
{
// finished!
if (difftime(time(NULL), last_check) >= DAY_IN_SECONDS)
{
last_check = last_check + DAY_IN_SECONDS;
}
else
{
last_check = last_check + HOUR_IN_SECONDS;
}
ena_storage_write_last_exposure_date(last_check);
current_page = 0;
request_sleep = 0;
request_sleep_waiting = 30;
ena_exposure_summary(ena_exposure_default_config());
ena_exposure_summary_t *current_summary = ena_exposure_current_summary();
ESP_LOGD(ENA_EKE_PROXY_LOG, "current summary\nlast update: %u\ndays_since_last_exposure: %d\nnum_exposures: %d\nmax_risk_score: %d\nrisk_score_sum: %d",
current_summary->last_update,
current_summary->days_since_last_exposure,
current_summary->num_exposures,
current_summary->max_risk_score,
current_summary->risk_score_sum);
}
else
{
current_page = 0;
request_sleep = time(NULL) + request_sleep_waiting;
if (request_sleep_waiting < HOUR_IN_SECONDS)
{
request_sleep_waiting = request_sleep_waiting * 3;
}
}
output_buffer = NULL;
output_len = 0;
wait_for_request = false;
break;
default:
break;
}
return ESP_OK;
}
esp_err_t ena_eke_proxy_receive_keys(char *url)
{
static int retries = 0;
wait_for_request = true;
esp_http_client_config_t config = {
.url = url,
.timeout_ms = 30000,
.event_handler = ena_eke_proxy_fetch_event_handler,
};
if (memcmp(url, "https", 5) == 0)
{
config.cert_pem = (char *)cert_pem_start;
}
ESP_LOGD(ENA_EKE_PROXY_LOG, "start request: url = %s | memory: %d kB", url, (xPortGetFreeHeapSize() / 1024));
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
int content_length = esp_http_client_get_content_length(client);
ESP_LOGD(ENA_EKE_PROXY_LOG, "finished request: url = %s, status = %d, content_length = %d | memory: %d kB", url,
esp_http_client_get_status_code(client),
content_length, (xPortGetFreeHeapSize() / 1024));
retries = 0;
}
free(url);
esp_http_client_close(client);
esp_http_client_cleanup(client);
if (err != ESP_OK && retries < 6)
{
retries = retries + 1;
ESP_LOGD(ENA_EKE_PROXY_LOG, "retry %d for url = %s", retries, url);
return ena_eke_proxy_receive_keys(url);
}
return err;
}
esp_err_t ena_eke_proxy_receive_daily_keys(char *date_string, size_t page, size_t size)
{
char *url = malloc(strlen(ENA_EKE_PROXY_KEYFILES_DAILY_URL) + strlen(date_string) + 16);
sprintf(url, ENA_EKE_PROXY_KEYFILES_DAILY_URL, date_string, page, size);
return ena_eke_proxy_receive_keys(url);
}
esp_err_t ena_eke_proxy_receive_hourly_keys(char *date_string, uint8_t hour, size_t page, size_t size)
{
char *url = malloc(strlen(ENA_EKE_PROXY_KEYFILES_HOURLY_URL) + strlen(date_string) + 24);
sprintf(url, ENA_EKE_PROXY_KEYFILES_HOURLY_URL, date_string, hour, page, size);
return ena_eke_proxy_receive_keys(url);
}
void ena_eke_proxy_run(void)
{
static time_t current_time = 0;
static struct tm current_tm;
static struct tm last_check_tm;
static double check_diff = 0;
static time_t wifi_reconnect = 0;
static uint32_t wifi_reconnect_waiting = 15;
current_time = time(NULL);
last_check = (time_t)ena_storage_read_last_exposure_date();
check_diff = difftime(current_time, last_check);
if (check_diff > HOUR_IN_SECONDS && !wait_for_request && current_time > request_sleep)
{
if (wifi_controller_connection() == NULL && current_time > wifi_reconnect && wifi_reconnect_waiting < 86400)
{
wifi_controller_reconnect(NULL);
wifi_reconnect = current_time + wifi_reconnect_waiting;
wifi_reconnect_waiting = wifi_reconnect_waiting * 4;
}
else if (wifi_controller_connection() != NULL)
{
wifi_reconnect = 0;
wifi_reconnect_waiting = 15;
int current_day_offset = check_diff / DAY_IN_SECONDS;
if (current_day_offset > ENA_EKE_PROXY_MAX_PAST_DAYS)
{
current_day_offset = ENA_EKE_PROXY_MAX_PAST_DAYS;
last_check = (current_time - (DAY_IN_SECONDS * current_day_offset));
}
memcpy(&current_tm, gmtime(&current_time), sizeof current_tm);
memcpy(&last_check_tm, gmtime(&last_check), sizeof last_check_tm);
if (current_day_offset > 0 || current_tm.tm_mday > last_check_tm.tm_mday || current_tm.tm_mon > last_check_tm.tm_mon)
{
last_check_tm.tm_hour = 0;
if (current_day_offset <= 0)
{
current_day_offset = 1;
}
}
last_check_tm.tm_min = 0;
last_check_tm.tm_sec = 0;
last_check = mktime(&last_check_tm);
esp_err_t err;
char date_string[11];
strftime(date_string, 11, ENA_EKE_PROXY_KEYFILES_DAILY_FORMAT, &last_check_tm);
if (current_day_offset == 0 && ENA_EKE_PROXY_KEYFILES_HOURLY)
{
ESP_LOGD(ENA_EKE_PROXY_LOG, "eke-proxy request for /%s/hour/%d?page=%d&size=%d : %d kB, ", date_string, last_check_tm.tm_hour, current_page, ENA_EKE_PROXY_DEFAULT_LIMIT, (xPortGetFreeHeapSize() / 1024));
err = ena_eke_proxy_receive_hourly_keys(date_string, last_check_tm.tm_hour, current_page, ENA_EKE_PROXY_DEFAULT_LIMIT);
}
else
{
ESP_LOGD(ENA_EKE_PROXY_LOG, "eke-proxy request for /%s?page=%d&size=%d : %d kB, ", date_string, current_page, ENA_EKE_PROXY_DEFAULT_LIMIT, (xPortGetFreeHeapSize() / 1024));
err = ena_eke_proxy_receive_daily_keys(date_string, current_page, ENA_EKE_PROXY_DEFAULT_LIMIT);
}
if (err != ESP_OK)
{
ESP_LOGD(ENA_EKE_PROXY_LOG, "error eke-proxy /%s/%u %d, ", date_string, last_check_tm.tm_hour, (xPortGetFreeHeapSize() / 1024));
}
}
}
}
esp_err_t ena_eke_proxy_fetch_upload_handler(esp_http_client_event_t *evt)
{
switch (evt->event_id)
{
case HTTP_EVENT_ON_DATA:
break;
case HTTP_EVENT_ON_FINISH:
break;
default:
break;
}
return ESP_OK;
}
esp_err_t ena_eke_proxy_upload(char *token, uint32_t days_since_onset_of_symptoms)
{
ESP_LOGD(ENA_EKE_PROXY_LOG, "try to upload keys:");
esp_http_client_config_t config = {
.url = ENA_EKE_PROXY_KEYFILES_UPLOAD_URL,
.timeout_ms = 30000,
.event_handler = ena_eke_proxy_fetch_upload_handler,
.method = HTTP_METHOD_POST,
};
if (memcmp(ENA_EKE_PROXY_KEYFILES_UPLOAD_URL, "https", 5) == 0)
{
config.cert_pem = (char *)cert_pem_start;
}
uint32_t tek_count = ena_storage_tek_count();
uint32_t teks_to_send = 0;
char *output_buffer = malloc(tek_count * 28);
ena_tek_t tek;
for (int i = 0; i < tek_count; i++)
{
ena_storage_get_tek(i, &tek);
if (((((uint32_t)time(NULL)) - (tek.enin * ENA_TIME_WINDOW)) / DAY_IN_SECONDS) < ENA_STORAGE_TEK_MAX)
{
memcpy(&output_buffer[teks_to_send * 28], &(tek.key_data), ENA_KEY_LENGTH);
memcpy(&output_buffer[teks_to_send * 28 + ENA_KEY_LENGTH], &(tek.enin), 4);
uint32_t rolling_period = tek.rolling_period;
memcpy(&output_buffer[teks_to_send * 28 + ENA_KEY_LENGTH + 4], &rolling_period, 4);
memcpy(&output_buffer[teks_to_send * 28 + ENA_KEY_LENGTH + 8], &days_since_onset_of_symptoms, 4);
teks_to_send++;
}
}
ESP_LOG_BUFFER_HEXDUMP(ENA_EKE_PROXY_LOG, output_buffer, teks_to_send * 28, ESP_LOG_DEBUG);
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_set_header(client, "Authorization", token);
esp_http_client_set_header(client, "Content-Type", "application/binary");
esp_http_client_set_header(client, "Accept", "application/octet-stream");
esp_http_client_set_post_field(client, output_buffer, teks_to_send * 28);
esp_err_t err = esp_http_client_perform(client);
if (err == ESP_OK)
{
int content_length = esp_http_client_get_content_length(client);
int status = esp_http_client_get_status_code(client);
if (status == 200)
{
ESP_LOGI(ENA_EKE_PROXY_LOG, "successfully uploaded keys : url = %s, status = %d, content_length = %d", ENA_EKE_PROXY_KEYFILES_UPLOAD_URL, status, content_length);
err = ESP_OK;
}
else
{
ESP_LOGW(ENA_EKE_PROXY_LOG, "failed to upload keys : url = %s, status = %d, content_length = %d", ENA_EKE_PROXY_KEYFILES_UPLOAD_URL, status, content_length);
err = ESP_FAIL;
}
}
else
{
ESP_LOGW(ENA_EKE_PROXY_LOG, "Keyupload failed!");
}
free(output_buffer);
esp_http_client_close(client);
esp_http_client_cleanup(client);
return err;
}
+77
View File
@@ -0,0 +1,77 @@
// Copyright 2020 Lukas Haubaum
//
// Licensed under the GNU Affero General Public License, Version 3;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// https://www.gnu.org/licenses/agpl-3.0.html
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/**
* @file
*
* @brief connection to an Exposure Key export proxy
*
* This is for receiving the Exposure Key export from a compatible proxy server and upload own infected keys to it.
*
*/
#ifndef _ena_EKE_PROXY_H_
#define _ena_EKE_PROXY_H_
#include "esp_err.h"
#include "ena-crypto.h"
#define ENA_EKE_PROXY_LOG "ESP-ENA-eke-proxy" // TAG for Logging
#define ENA_EKE_PROXY_KEYFILES_DAILY_URL CONFIG_ENA_EKE_PROXY_KEYFILES_DAILY_URL
#define ENA_EKE_PROXY_KEYFILES_HOURLY CONFIG_ENA_EKE_PROXY_KEYFILES_HOURLY
#define ENA_EKE_PROXY_KEYFILES_HOURLY_URL CONFIG_ENA_EKE_PROXY_KEYFILES_HOURLY_URL
#define ENA_EKE_PROXY_KEYFILES_DAILY_FORMAT CONFIG_ENA_EKE_PROXY_KEYFILES_DAILY_FORMAT
#define ENA_EKE_PROXY_KEYFILES_UPLOAD_URL CONFIG_ENA_EKE_PROXY_KEYFILES_UPLOAD_URL
#define ENA_EKE_PROXY_DEFAULT_LIMIT CONFIG_ENA_EKE_PROXY_KEY_LIMIT
#define ENA_EKE_PROXY_MAX_PAST_DAYS CONFIG_ENA_EKE_PROXY_MAX_PAST_DAYS // ENA_STORAGE_TEK_MAX
/**
* @brief fetch key export from given url
*
* @param[in] url the url to fetch the data from
*/
esp_err_t ena_eke_proxy_receive_keys(char *url);
/**
* @brief fetch key export for given date with limit and offset
*
* @param[in] date_string the date to fetch the data for
* @param[in] page the page to request
* @param[in] size the size of a page
*/
esp_err_t ena_eke_proxy_receive_daily_keys(char *date_string, size_t page, size_t size);
/**
* @brief fetch key export for given date with limit and offset
*
* @param[in] date_string the date to fetch the data for
* @param[in] hour the hour to fetch the data for
* @param[in] page the page to request
* @param[in] size the size of a page
*/
esp_err_t ena_eke_proxy_receive_hourly_keys(char *date_string, uint8_t hour, size_t page, size_t size);
/**
* @brief run ena eke proxy
*/
void ena_eke_proxy_run(void);
/**
* @brief Upload own keys to server
*
* @param[in] token token for authentication
* @param[in] days_since_onset_of_symptomstoken days after test/symptoms?
*/
esp_err_t ena_eke_proxy_upload(char *token, uint32_t days_since_onset_of_symptoms);
#endif