mirror of
https://github.com/Lurkars/esp-ena.git
synced 2026-05-08 20:10:37 +02:00
update to support ena-eke-proxy
This commit is contained in:
@@ -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
|
||||
@@ -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-----
|
||||
@@ -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(¤t_tm, gmtime(¤t_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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user