added EVCSInfo to SAEMs

This commit is contained in:
gilteixeira 2023-03-01 16:01:52 +00:00
parent 948780526b
commit dfbc7bf866
5 changed files with 716 additions and 390 deletions

View File

@ -13,6 +13,9 @@
"asn_application.h": "c", "asn_application.h": "c",
"itspduheader.h": "c", "itspduheader.h": "c",
"evchargingspotnotificationpoimessage.h": "c", "evchargingspotnotificationpoimessage.h": "c",
"vcm.h": "c" "vcm.h": "c",
"constr_sequence_of.h": "c",
"asn_internal.h": "c",
"bit_string.h": "c"
} }
} }

View File

@ -13,6 +13,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <it2s-asn/camv2/ProtectedCommunicationZone.h> #include <it2s-asn/camv2/ProtectedCommunicationZone.h>
#include <it2s-asn/tpm/TollingPaymentInfo.h> #include <it2s-asn/tpm/TollingPaymentInfo.h>
#include <it2s-asn/evcsnm/EVCSInfo.h>
#include <zmq.h> #include <zmq.h>
#include <it2s-tender/packet.h> #include <it2s-tender/packet.h>
@ -22,23 +23,29 @@
#include <it2s-asn/itss-security/SecurityRequest.h> #include <it2s-asn/itss-security/SecurityRequest.h>
#include <it2s-asn/itss-security/SecurityReply.h> #include <it2s-asn/itss-security/SecurityReply.h>
static int fetch_target_address(char** addresses, uint16_t addresses_len) { static int fetch_target_address(char **addresses, uint16_t addresses_len)
{
int index = -1; int index = -1;
for (int i = 0; i < addresses_len; ++i) { for (int i = 0; i < addresses_len; ++i)
{
char *addr = addresses[i]; char *addr = addresses[i];
// If TCP, ignore receiver addresses, e.g. tcp://*:[port] // If TCP, ignore receiver addresses, e.g. tcp://*:[port]
if (!memcmp(addr, "tcp", 3)) { if (!memcmp(addr, "tcp", 3))
{
bool found_astk = false; bool found_astk = false;
for (int j = 0; j < strlen(addr); ++j) { for (int j = 0; j < strlen(addr); ++j)
if (addr[j] == '*') { {
if (addr[j] == '*')
{
found_astk = true; found_astk = true;
break; break;
} }
} }
if (found_astk) continue; if (found_astk)
continue;
} }
index = i; index = i;
@ -48,24 +55,32 @@ static int fetch_target_address(char** addresses, uint16_t addresses_len) {
return index; return index;
} }
int facilities_config() { int facilities_config()
{
int rv = 0; int rv = 0;
it2s_config_t *config = calloc(1, sizeof(it2s_config_t)); it2s_config_t *config = calloc(1, sizeof(it2s_config_t));
rv = it2s_config_read("/etc/it2s/itss.toml", config); rv = it2s_config_read("/etc/it2s/itss.toml", config);
if (rv) { if (rv)
{
log_error("[config] read config failed"); log_error("[config] read config failed");
goto cleanup; goto cleanup;
} }
// Logging - status messages // Logging - status messages
bool use_syslog = false, use_std = false, use_file = false; bool use_syslog = false, use_std = false, use_file = false;
for (int i = 0; i < config->general.logging.status_len; ++i) { for (int i = 0; i < config->general.logging.status_len; ++i)
if (!strcmp(config->general.logging.status[i], "syslog")) { {
if (!strcmp(config->general.logging.status[i], "syslog"))
{
use_syslog = true; use_syslog = true;
} else if (!strcmp(config->general.logging.status[i], "std")) { }
else if (!strcmp(config->general.logging.status[i], "std"))
{
use_std = true; use_std = true;
} else if (!strcmp(config->general.logging.status[i], "file")) { }
else if (!strcmp(config->general.logging.status[i], "file"))
{
use_file = true; use_file = true;
} }
} }
@ -85,16 +100,20 @@ int facilities_config() {
facilities.zmq.responders[0].socket = socket; facilities.zmq.responders[0].socket = socket;
facilities.zmq.responders[0].events = ZMQ_POLLIN; facilities.zmq.responders[0].events = ZMQ_POLLIN;
for (int i = 0; i < config->facilities.zmq.addresses_len; ++i) { for (int i = 0; i < config->facilities.zmq.addresses_len; ++i)
{
char *addr = config->facilities.zmq.addresses[i]; char *addr = config->facilities.zmq.addresses[i];
// IPC // IPC
if (!memcmp(addr, "ipc", 3)) { if (!memcmp(addr, "ipc", 3))
{
// Create dir // Create dir
int lp = 0; int lp = 0;
for (int j = 0; j < strlen(addr); ++j) { for (int j = 0; j < strlen(addr); ++j)
if (addr[j] == '/') lp = j; {
if (addr[j] == '/')
lp = j;
} }
char dir[256]; char dir[256];
@ -102,7 +121,8 @@ int facilities_config() {
dir[lp - 6] = 0; dir[lp - 6] = 0;
struct stat st = {0}; struct stat st = {0};
if (stat(dir, &st) == -1) { if (stat(dir, &st) == -1)
{
mkdir(dir, 0777); mkdir(dir, 0777);
} }
@ -112,18 +132,22 @@ int facilities_config() {
facilities.zmq.responders[facilities.zmq.n_responders].socket = socket; facilities.zmq.responders[facilities.zmq.n_responders].socket = socket;
facilities.zmq.responders[facilities.zmq.n_responders].events = ZMQ_POLLIN; facilities.zmq.responders[facilities.zmq.n_responders].events = ZMQ_POLLIN;
++facilities.zmq.n_responders; ++facilities.zmq.n_responders;
}
} else if (!memcmp(addr, "tcp", 3)) { else if (!memcmp(addr, "tcp", 3))
{
bool found_astk = false; bool found_astk = false;
for (int j = 0; j < strlen(addr); ++j) { for (int j = 0; j < strlen(addr); ++j)
if (addr[j] == '*') { {
if (addr[j] == '*')
{
found_astk = true; found_astk = true;
break; break;
} }
} }
if (found_astk) { if (found_astk)
{
// Bind // Bind
void *socket = itss_0bind(addr, ZMQ_REP); void *socket = itss_0bind(addr, ZMQ_REP);
@ -133,7 +157,8 @@ int facilities_config() {
} }
} }
} }
if (facilities.zmq.n_responders <= 1) { if (facilities.zmq.n_responders <= 1)
{
log_info("[config] a valid address to listen to was not found, exiting now"); log_info("[config] a valid address to listen to was not found, exiting now");
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -141,10 +166,13 @@ int facilities_config() {
// Fetch [transport] address // Fetch [transport] address
int index = fetch_target_address(config->transport.zmq.addresses, config->transport.zmq.addresses_len); int index = fetch_target_address(config->transport.zmq.addresses, config->transport.zmq.addresses_len);
if (index != -1) { if (index != -1)
{
facilities.zmq.transport_address = malloc(strlen(config->transport.zmq.addresses[index]) + 1); facilities.zmq.transport_address = malloc(strlen(config->transport.zmq.addresses[index]) + 1);
strcpy(facilities.zmq.transport_address, config->transport.zmq.addresses[index]); strcpy(facilities.zmq.transport_address, config->transport.zmq.addresses[index]);
} else { }
else
{
log_error("[config] a valid address for [transport] was not found"); log_error("[config] a valid address for [transport] was not found");
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -152,10 +180,13 @@ int facilities_config() {
// Fetch [applications] address // Fetch [applications] address
index = fetch_target_address(config->applications.zmq.addresses, config->applications.zmq.addresses_len); index = fetch_target_address(config->applications.zmq.addresses, config->applications.zmq.addresses_len);
if (index != -1) { if (index != -1)
{
facilities.zmq.applications_address = malloc(strlen(config->applications.zmq.addresses[index]) + 1); facilities.zmq.applications_address = malloc(strlen(config->applications.zmq.addresses[index]) + 1);
strcpy(facilities.zmq.applications_address, config->applications.zmq.addresses[index]); strcpy(facilities.zmq.applications_address, config->applications.zmq.addresses[index]);
} else { }
else
{
log_error("[config] a valid address for [applications] was not found"); log_error("[config] a valid address for [applications] was not found");
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -163,10 +194,13 @@ int facilities_config() {
// Fetch [security] address // Fetch [security] address
index = fetch_target_address(config->security.zmq.addresses, config->security.zmq.addresses_len); index = fetch_target_address(config->security.zmq.addresses, config->security.zmq.addresses_len);
if (index != -1) { if (index != -1)
{
facilities.zmq.security_address = malloc(strlen(config->security.zmq.addresses[index]) + 1); facilities.zmq.security_address = malloc(strlen(config->security.zmq.addresses[index]) + 1);
strcpy(facilities.zmq.security_address, config->security.zmq.addresses[index]); strcpy(facilities.zmq.security_address, config->security.zmq.addresses[index]);
} else { }
else
{
log_error("[config] a valid address for [security] was not found"); log_error("[config] a valid address for [security] was not found");
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -174,10 +208,13 @@ int facilities_config() {
// Fetch [management] address // Fetch [management] address
index = fetch_target_address(config->management.zmq.addresses, config->management.zmq.addresses_len); index = fetch_target_address(config->management.zmq.addresses, config->management.zmq.addresses_len);
if (index != -1) { if (index != -1)
{
facilities.zmq.management_address = malloc(strlen(config->management.zmq.addresses[index]) + 1); facilities.zmq.management_address = malloc(strlen(config->management.zmq.addresses[index]) + 1);
strcpy(facilities.zmq.management_address, config->management.zmq.addresses[index]); strcpy(facilities.zmq.management_address, config->management.zmq.addresses[index]);
} else { }
else
{
log_error("[config] a valid address for [management] was not found"); log_error("[config] a valid address for [management] was not found");
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -185,49 +222,80 @@ int facilities_config() {
// Values // Values
// General // General
if (!strcmp("obu", config->general.itss_type)) { if (!strcmp("obu", config->general.itss_type))
{
facilities.station_type = 5; facilities.station_type = 5;
} else if (!strcmp("rsu", config->general.itss_type)) { }
else if (!strcmp("rsu", config->general.itss_type))
{
facilities.station_type = 15; facilities.station_type = 15;
} else if (!strcmp("unknown", config->general.itss_type)) { }
else if (!strcmp("unknown", config->general.itss_type))
{
facilities.station_type = 0; facilities.station_type = 0;
} else if (!strcmp("pedestrian", config->general.itss_type)) { }
else if (!strcmp("pedestrian", config->general.itss_type))
{
facilities.station_type = 1; facilities.station_type = 1;
} else if (!strcmp("cyclist", config->general.itss_type)) { }
else if (!strcmp("cyclist", config->general.itss_type))
{
facilities.station_type = 2; facilities.station_type = 2;
} else if (!strcmp("moped", config->general.itss_type)) { }
else if (!strcmp("moped", config->general.itss_type))
{
facilities.station_type = 3; facilities.station_type = 3;
} else if (!strcmp("motorcycle", config->general.itss_type)) { }
else if (!strcmp("motorcycle", config->general.itss_type))
{
facilities.station_type = 4; facilities.station_type = 4;
} else if (!strcmp("passengerCar", config->general.itss_type)) { }
else if (!strcmp("passengerCar", config->general.itss_type))
{
facilities.station_type = 5; facilities.station_type = 5;
} else if (!strcmp("bus", config->general.itss_type)) { }
else if (!strcmp("bus", config->general.itss_type))
{
facilities.station_type = 6; facilities.station_type = 6;
} else if (!strcmp("lightTruck", config->general.itss_type)) { }
else if (!strcmp("lightTruck", config->general.itss_type))
{
facilities.station_type = 7; facilities.station_type = 7;
} else if (!strcmp("heavyTruck", config->general.itss_type)) { }
else if (!strcmp("heavyTruck", config->general.itss_type))
{
facilities.station_type = 8; facilities.station_type = 8;
} else if (!strcmp("trailer", config->general.itss_type)) { }
else if (!strcmp("trailer", config->general.itss_type))
{
facilities.station_type = 9; facilities.station_type = 9;
} else if (!strcmp("specialVehicles", config->general.itss_type)) { }
else if (!strcmp("specialVehicles", config->general.itss_type))
{
facilities.station_type = 10; facilities.station_type = 10;
} else if (!strcmp("tram", config->general.itss_type)) { }
else if (!strcmp("tram", config->general.itss_type))
{
facilities.station_type = 11; facilities.station_type = 11;
} else if (!strcmp("roadSideUnit", config->general.itss_type)) { }
else if (!strcmp("roadSideUnit", config->general.itss_type))
{
facilities.station_type = 15; facilities.station_type = 15;
} else { }
else
{
log_error("[config] unrecognized ITS-S type, running as OBU"); log_error("[config] unrecognized ITS-S type, running as OBU");
facilities.station_type = 5; facilities.station_type = 5;
} }
facilities.use_security = config->security.use_security; facilities.use_security = config->security.use_security;
pthread_mutex_init(&facilities.id.lock, NULL); pthread_mutex_init(&facilities.id.lock, NULL);
pthread_mutex_init(&facilities.id.change.lock, NULL); pthread_mutex_init(&facilities.id.change.lock, NULL);
facilities.id.change.random = config->security.identity.random; facilities.id.change.random = config->security.identity.random;
if (facilities.id.change.random) { if (facilities.id.change.random)
{
// Ask [security] for station id // Ask [security] for station id
SecurityRequest_t *sREQ = calloc(1, sizeof(SecurityRequest_t)); SecurityRequest_t *sREQ = calloc(1, sizeof(SecurityRequest_t));
@ -249,20 +317,24 @@ int facilities_config() {
itss_0send(ss, b_tx, enc.encoded); itss_0send(ss, b_tx, enc.encoded);
int rl = itss_0recv_rt(&ss, b_rx, 256, b_tx, 256, -1); int rl = itss_0recv_rt(&ss, b_rx, 256, b_tx, 256, -1);
itss_0close(ss); itss_0close(ss);
if (rl == -1) { if (rl == -1)
{
rv = 1; rv = 1;
goto cleanup; goto cleanup;
} }
asn_dec_rval_t dec = oer_decode(NULL, &asn_DEF_SecurityReply, (void **)&sREP, b_rx, 256); asn_dec_rval_t dec = oer_decode(NULL, &asn_DEF_SecurityReply, (void **)&sREP, b_rx, 256);
if (sREP->returnCode == SecurityReplyReturnCode_rejected) { if (sREP->returnCode == SecurityReplyReturnCode_rejected)
{
// TODO handle it // TODO handle it
goto cleanup; goto cleanup;
} }
for (int i = 0; i < sREP->data->choice.ids.list.count; ++i) { for (int i = 0; i < sREP->data->choice.ids.list.count; ++i)
switch (sREP->data->choice.ids.list.array[i]->present) { {
switch (sREP->data->choice.ids.list.array[i]->present)
{
case SecurityId_PR_stationId: case SecurityId_PR_stationId:
facilities.id.station_id = sREP->data->choice.ids.list.array[i]->choice.stationId; facilities.id.station_id = sREP->data->choice.ids.list.array[i]->choice.stationId;
break; break;
@ -276,8 +348,9 @@ int facilities_config() {
ASN_STRUCT_FREE(asn_DEF_SecurityRequest, sREQ); ASN_STRUCT_FREE(asn_DEF_SecurityRequest, sREQ);
ASN_STRUCT_FREE(asn_DEF_SecurityReply, sREP); ASN_STRUCT_FREE(asn_DEF_SecurityReply, sREP);
}
} else { else
{
facilities.id.station_id = config->security.identity.station_id; facilities.id.station_id = config->security.identity.station_id;
uint8_t src_mac[6]; uint8_t src_mac[6];
@ -306,7 +379,6 @@ int facilities_config() {
facilities.id.ipv6_addr[8] ^= 0x02; facilities.id.ipv6_addr[8] ^= 0x02;
} }
// DENM // DENM
facilities.den.n_max_events = config->facilities.denm.nmax_active_events; facilities.den.n_max_events = config->facilities.denm.nmax_active_events;
@ -341,15 +413,24 @@ int facilities_config() {
// TPM // TPM
facilities.tolling.enabled = config->facilities.tpm.activate; facilities.tolling.enabled = config->facilities.tpm.activate;
if (!strcmp("simple", config->facilities.tpm.protocol)) { if (!strcmp("simple", config->facilities.tpm.protocol))
{
facilities.tolling.protocol.p = TOLLING_PROTOCOL_SIMPLE; facilities.tolling.protocol.p = TOLLING_PROTOCOL_SIMPLE;
} else if (!strcmp("tls", config->facilities.tpm.protocol)) { }
else if (!strcmp("tls", config->facilities.tpm.protocol))
{
facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS; facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS;
} else if (!strcmp("tls-gn", config->facilities.tpm.protocol)) { }
else if (!strcmp("tls-gn", config->facilities.tpm.protocol))
{
facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS_GN; facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS_GN;
} else if (!strcmp("tls-shs", config->facilities.tpm.protocol)) { }
else if (!strcmp("tls-shs", config->facilities.tpm.protocol))
{
facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS_SHS; facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS_SHS;
} else { }
else
{
log_error("[config] unrecognized tolling protocol, defaulting to 'simple'"); log_error("[config] unrecognized tolling protocol, defaulting to 'simple'");
facilities.tolling.protocol.p = TOLLING_PROTOCOL_SIMPLE; facilities.tolling.protocol.p = TOLLING_PROTOCOL_SIMPLE;
} }
@ -357,37 +438,58 @@ int facilities_config() {
// MCM // MCM
facilities.coordination.active = config->facilities.mcm.activate; facilities.coordination.active = config->facilities.mcm.activate;
if (!strcmp("vcm-RR", config->facilities.mcm.protocol)) { if (!strcmp("vcm-RR", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR;
facilities.coordination.chain.enabled = true; facilities.coordination.chain.enabled = true;
} else if (!strcmp("vcm-RR1C", config->facilities.mcm.protocol)) { }
else if (!strcmp("vcm-RR1C", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C;
facilities.coordination.chain.enabled = true; facilities.coordination.chain.enabled = true;
} else if (!strcmp("vcm-RR1Cc", config->facilities.mcm.protocol)) { }
else if (!strcmp("vcm-RR1Cc", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C;
facilities.coordination.chain.enabled = true; facilities.coordination.chain.enabled = true;
} else if (!strcmp("vcm-RRAC", config->facilities.mcm.protocol)) { }
else if (!strcmp("vcm-RRAC", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC; facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC;
facilities.coordination.chain.enabled = true; facilities.coordination.chain.enabled = true;
} else if (!strcmp("vcm-RRACc", config->facilities.mcm.protocol)) { }
else if (!strcmp("vcm-RRACc", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC; facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC;
facilities.coordination.chain.enabled = true; facilities.coordination.chain.enabled = true;
} else if (!strcmp("evcm-RR-PBFT", config->facilities.mcm.protocol)) { }
else if (!strcmp("evcm-RR-PBFT", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR;
facilities.coordination.chain.enabled = false; facilities.coordination.chain.enabled = false;
} else if (!strcmp("evcm-RR1C-PBFT", config->facilities.mcm.protocol)) { }
else if (!strcmp("evcm-RR1C-PBFT", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C;
facilities.coordination.chain.enabled = false; facilities.coordination.chain.enabled = false;
} else if (!strcmp("evcm-RR1Cc-PBFT", config->facilities.mcm.protocol)) { }
else if (!strcmp("evcm-RR1Cc-PBFT", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C;
facilities.coordination.chain.enabled = false; facilities.coordination.chain.enabled = false;
} else if (!strcmp("evcm-RRAC-PBFT", config->facilities.mcm.protocol)) { }
else if (!strcmp("evcm-RRAC-PBFT", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC; facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC;
facilities.coordination.chain.enabled = false; facilities.coordination.chain.enabled = false;
} else if (!strcmp("evcm-RRACc-PBFT", config->facilities.mcm.protocol)) { }
else if (!strcmp("evcm-RRACc-PBFT", config->facilities.mcm.protocol))
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC; facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC;
facilities.coordination.chain.enabled = false; facilities.coordination.chain.enabled = false;
} else { }
else
{
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR; facilities.coordination.protocol = MC_PROTOCOL_VCM_RR;
facilities.coordination.chain.enabled = true; facilities.coordination.chain.enabled = true;
} }
@ -396,12 +498,65 @@ int facilities_config() {
// EVCSNM // EVCSNM
facilities.evcsnm_args.activate = config->facilities.evcsnm.activate; facilities.evcsnm_args.activate = config->facilities.evcsnm.activate;
if (facilities.station_type == 15)
{
int i = 0;
DIR *d = opendir(config->facilities.evcsnm.evcsi_path);
struct dirent *dir;
char file[256];
char ti_xml[2048];
if (d)
{
while ((dir = readdir(d)) != NULL && i < EVCSNM_INFOS_MAX_LENGTH)
{
if (dir->d_name[0] == '.')
continue;
sprintf(file, "%s/%s", config->facilities.evcsnm.evcsi_path, dir->d_name);
FILE *fp = fopen(file, "r");
if (!fp)
continue;
fseek(fp, 0, SEEK_END);
uint16_t size = ftell(fp);
fseek(fp, 0, SEEK_SET);
if (!size)
{
fclose(fp);
continue;
}
if (!fread(ti_xml, 1, size, fp))
{
fclose(fp);
continue;
}
fclose(fp);
EVCSInfo_t *ti = calloc(1, sizeof(EVCSInfo_t));
asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_EVCSInfo, (void **)&ti, ti_xml, size);
if (!dec.code)
{
facilities.evcsnm_args.infos.z[i] = calloc(1, sizeof(evcs_info_t));
facilities.evcsnm_args.infos.z[i]->asn = ti;
++facilities.evcsnm_args.infos.length;
++i;
log_debug("[config] loaded evcs info | id:%lld", ti->id);
}
else
{
log_error("[config] failure to decode evcs info '%s'", dir->d_name);
ASN_STRUCT_FREE(asn_DEF_EVCSInfo, ti);
}
}
closedir(d);
}
}
// Replay // Replay
facilities.replay = config->networking.replay.activate; facilities.replay = config->networking.replay.activate;
// PZ // PZ
if (facilities.station_type == 15) { if (facilities.station_type == 15)
{
int i = 0; int i = 0;
@ -409,20 +564,26 @@ int facilities_config() {
struct dirent *dir; struct dirent *dir;
char file[256]; char file[256];
char pz_xml[2048]; char pz_xml[2048];
if (d) { if (d)
while ((dir = readdir(d)) != NULL && i < 16) { {
if (dir->d_name[0] == '.') continue; while ((dir = readdir(d)) != NULL && i < 16)
{
if (dir->d_name[0] == '.')
continue;
sprintf(file, "%s/%s", config->facilities.protected_zones.path, dir->d_name); sprintf(file, "%s/%s", config->facilities.protected_zones.path, dir->d_name);
FILE *fp = fopen(file, "r"); FILE *fp = fopen(file, "r");
if (!fp) continue; if (!fp)
continue;
fseek(fp, 0, SEEK_END); fseek(fp, 0, SEEK_END);
uint16_t size = ftell(fp); uint16_t size = ftell(fp);
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
if (!size) { if (!size)
{
fclose(fp); fclose(fp);
continue; continue;
} }
if (!fread(pz_xml, 1, size, fp)) { if (!fread(pz_xml, 1, size, fp))
{
fclose(fp); fclose(fp);
continue; continue;
} }
@ -431,23 +592,26 @@ int facilities_config() {
ProtectedCommunicationZone_t *zone = calloc(1, sizeof(ProtectedCommunicationZone_t)); ProtectedCommunicationZone_t *zone = calloc(1, sizeof(ProtectedCommunicationZone_t));
asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_ProtectedCommunicationZone, (void **)&zone, pz_xml, size); asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_ProtectedCommunicationZone, (void **)&zone, pz_xml, size);
if (!dec.code) { if (!dec.code)
{
facilities.lightship.protected_zones.pz[i] = zone; facilities.lightship.protected_zones.pz[i] = zone;
++facilities.lightship.protected_zones.pz_len; ++facilities.lightship.protected_zones.pz_len;
++i; ++i;
log_debug("[config] loaded protection zone @ (%lld, %lld)", zone->protectedZoneLatitude, zone->protectedZoneLongitude); log_debug("[config] loaded protection zone @ (%lld, %lld)", zone->protectedZoneLatitude, zone->protectedZoneLongitude);
} else { }
else
{
log_error("[config] failure to decode protection zone '%s'", dir->d_name); log_error("[config] failure to decode protection zone '%s'", dir->d_name);
ASN_STRUCT_FREE(asn_DEF_ProtectedCommunicationZone, zone); ASN_STRUCT_FREE(asn_DEF_ProtectedCommunicationZone, zone);
} }
} }
closedir(d); closedir(d);
} }
} }
// TZ // TZ
if (facilities.station_type == 15) { if (facilities.station_type == 15)
{
int i = 0; int i = 0;
@ -455,20 +619,26 @@ int facilities_config() {
struct dirent *dir; struct dirent *dir;
char file[256]; char file[256];
char ti_xml[2048]; char ti_xml[2048];
if (d) { if (d)
while ((dir = readdir(d)) != NULL && i < TOLLING_INFOS_MAX_LENGTH) { {
if (dir->d_name[0] == '.') continue; while ((dir = readdir(d)) != NULL && i < TOLLING_INFOS_MAX_LENGTH)
{
if (dir->d_name[0] == '.')
continue;
sprintf(file, "%s/%s", config->facilities.tpm.tis_path, dir->d_name); sprintf(file, "%s/%s", config->facilities.tpm.tis_path, dir->d_name);
FILE *fp = fopen(file, "r"); FILE *fp = fopen(file, "r");
if (!fp) continue; if (!fp)
continue;
fseek(fp, 0, SEEK_END); fseek(fp, 0, SEEK_END);
uint16_t size = ftell(fp); uint16_t size = ftell(fp);
fseek(fp, 0, SEEK_SET); fseek(fp, 0, SEEK_SET);
if (!size) { if (!size)
{
fclose(fp); fclose(fp);
continue; continue;
} }
if (!fread(ti_xml, 1, size, fp)) { if (!fread(ti_xml, 1, size, fp))
{
fclose(fp); fclose(fp);
continue; continue;
} }
@ -477,20 +647,22 @@ int facilities_config() {
TollingPaymentInfo_t *ti = calloc(1, sizeof(TollingPaymentInfo_t)); TollingPaymentInfo_t *ti = calloc(1, sizeof(TollingPaymentInfo_t));
asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_TollingPaymentInfo, (void **)&ti, ti_xml, size); asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_TollingPaymentInfo, (void **)&ti, ti_xml, size);
if (!dec.code) { if (!dec.code)
{
facilities.tolling.infos.z[i] = calloc(1, sizeof(tolling_info_t)); facilities.tolling.infos.z[i] = calloc(1, sizeof(tolling_info_t));
facilities.tolling.infos.z[i]->asn = ti; facilities.tolling.infos.z[i]->asn = ti;
++facilities.tolling.infos.length; ++facilities.tolling.infos.length;
++i; ++i;
log_debug("[config] loaded tolling info | id:%lld type:%s", log_debug("[config] loaded tolling info | id:%lld type:%s",
ti->id, ti->id,
ti->tollType==TollType_entry ? "entry": ti->tollType==TollType_exit ? "exit": "single" ti->tollType == TollType_entry ? "entry" : ti->tollType == TollType_exit ? "exit"
); : "single");
} else { }
else
{
log_error("[config] failure to decode tolling info '%s'", dir->d_name); log_error("[config] failure to decode tolling info '%s'", dir->d_name);
ASN_STRUCT_FREE(asn_DEF_TollingPaymentInfo, ti); ASN_STRUCT_FREE(asn_DEF_TollingPaymentInfo, ti);
} }
} }
closedir(d); closedir(d);
} }
@ -518,7 +690,8 @@ int facilities_config() {
itss_0send(management_socket, b_tx, enc.encoded); itss_0send(management_socket, b_tx, enc.encoded);
int rl = itss_0recv_rt(&management_socket, b_rx, 256, b_tx, 256, -1); int rl = itss_0recv_rt(&management_socket, b_rx, 256, b_tx, 256, -1);
itss_0close(management_socket); itss_0close(management_socket);
if (rl == -1) { if (rl == -1)
{
rv = 1; rv = 1;
goto cleanup; goto cleanup;
} }
@ -537,7 +710,8 @@ int facilities_config() {
mrep->data->choice.attributes.clock && mrep->data->choice.attributes.clock &&
mrep->data->choice.attributes.clockOffset && mrep->data->choice.attributes.clockOffset &&
mrep->data->choice.attributes.gpsType && mrep->data->choice.attributes.gpsType &&
(!!mrep->data->choice.attributes.trajectory == mreq->choice.attributes.choice.get.trajectory)) { (!!mrep->data->choice.attributes.trajectory == mreq->choice.attributes.choice.get.trajectory))
{
epv.space.latitude = mrep->data->choice.attributes.coordinates->latitude; epv.space.latitude = mrep->data->choice.attributes.coordinates->latitude;
epv.space.latitude_conf = mrep->data->choice.attributes.coordinates->latitudeConfidence; epv.space.latitude_conf = mrep->data->choice.attributes.coordinates->latitudeConfidence;
epv.space.longitude = mrep->data->choice.attributes.coordinates->longitude; epv.space.longitude = mrep->data->choice.attributes.coordinates->longitude;
@ -556,15 +730,19 @@ int facilities_config() {
asn_INTEGER2ulong(mrep->data->choice.attributes.clock, (unsigned long long *)&epv.time.clock); asn_INTEGER2ulong(mrep->data->choice.attributes.clock, (unsigned long long *)&epv.time.clock);
asn_INTEGER2ulong(mrep->data->choice.attributes.clockOffset, (unsigned long long *)&epv.time.offset); asn_INTEGER2ulong(mrep->data->choice.attributes.clockOffset, (unsigned long long *)&epv.time.offset);
if (config->facilities.mcm.activate) { if (config->facilities.mcm.activate)
{
epv.trajectory.len = mrep->data->choice.attributes.trajectory->list.count; epv.trajectory.len = mrep->data->choice.attributes.trajectory->list.count;
for (int i = 0; i < mrep->data->choice.attributes.trajectory->list.count; ++i) { for (int i = 0; i < mrep->data->choice.attributes.trajectory->list.count; ++i)
{
epv.trajectory.path[i].latitude = mrep->data->choice.attributes.trajectory->list.array[i]->latitude; epv.trajectory.path[i].latitude = mrep->data->choice.attributes.trajectory->list.array[i]->latitude;
epv.trajectory.path[i].longitude = mrep->data->choice.attributes.trajectory->list.array[i]->longitude; epv.trajectory.path[i].longitude = mrep->data->choice.attributes.trajectory->list.array[i]->longitude;
asn_INTEGER2ulong(&mrep->data->choice.attributes.trajectory->list.array[i]->timestamp, (unsigned long long *)&epv.trajectory.path[i].timestamp); asn_INTEGER2ulong(&mrep->data->choice.attributes.trajectory->list.array[i]->timestamp, (unsigned long long *)&epv.trajectory.path[i].timestamp);
} }
} }
} else { }
else
{
log_error("rejected MR attribute request"); log_error("rejected MR attribute request");
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -572,11 +750,23 @@ int facilities_config() {
ASN_STRUCT_FREE(asn_DEF_ManagementRequest, mreq); ASN_STRUCT_FREE(asn_DEF_ManagementRequest, mreq);
ASN_STRUCT_FREE(asn_DEF_ManagementReply, mrep); ASN_STRUCT_FREE(asn_DEF_ManagementReply, mrep);
if (config->facilities.saem.activate) { // TODO handle various services if (config->facilities.saem.activate)
{ // TODO handle various services
facilities.bulletin.to_provide_len = 1; facilities.bulletin.to_provide_len = 1;
facilities.bulletin.to_provide[0] = calloc(1, sizeof(announcement_t)); facilities.bulletin.to_provide[0] = calloc(1, sizeof(announcement_t));
facilities.bulletin.to_provide[0]->endpoint.port = 7010 + config->facilities.saem.service_to_advertise;
facilities.bulletin.to_provide[0]->its_aid = config->facilities.saem.service_to_advertise; facilities.bulletin.to_provide[0]->its_aid = config->facilities.saem.service_to_advertise;
switch (config->facilities.saem.service_to_advertise)
{
case SAID_ETC:
facilities.bulletin.to_provide[0]->endpoint.port = 7011;
break;
case SAID_EVCSN:
facilities.bulletin.to_provide[0]->endpoint.port = Port_poi;
break;
default:
log_error("unknown service to advertise! [config.c:facilities.saem.service_to_advertise]");
break;
}
} }
facilities.vehicle.length = config->facilities.vehicle.length; facilities.vehicle.length = config->facilities.vehicle.length;
@ -585,7 +775,8 @@ int facilities_config() {
// Logging // Logging
facilities.logging.recorder = config->facilities.logging.management; facilities.logging.recorder = config->facilities.logging.management;
if (config->general.logging.enabled && config->facilities.logging.dbms) { if (config->general.logging.enabled && config->facilities.logging.dbms)
{
facilities.logging.dbms = calloc(1, sizeof(itss_db_t)); facilities.logging.dbms = calloc(1, sizeof(itss_db_t));
if (itss_db_init( if (itss_db_init(
facilities.logging.dbms, facilities.logging.dbms,
@ -595,8 +786,8 @@ int facilities_config() {
config->general.logging.host, config->general.logging.host,
config->general.logging.port, config->general.logging.port,
config->general.logging.username, config->general.logging.username,
config->general.logging.password config->general.logging.password))
)) { {
log_error("failed to initialize the database -> turning off logging"); log_error("failed to initialize the database -> turning off logging");
free(facilities.logging.dbms); free(facilities.logging.dbms);
facilities.logging.dbms = NULL; facilities.logging.dbms = NULL;
@ -608,4 +799,3 @@ cleanup:
return rv; return rv;
} }

View File

@ -220,3 +220,18 @@ void *evcsn_service()
return NULL; return NULL;
} }
evcs_info_t* evcs_info_new(EVCSInfo_t* tpi) {
evcs_info_t* ti = calloc(1, sizeof(evcs_info_t));
ti->timestamp = itss_time_get();
ti->asn = tpi;
return ti;
}
void evcs_info_free(evcs_info_t* ti) {
ASN_STRUCT_FREE(asn_DEF_EVCSInfo, ti->asn);
free(ti);
}

View File

@ -7,14 +7,16 @@
#include <stdbool.h> #include <stdbool.h>
#include <it2s-asn/evcsnm/EvcsnPdu.h> #include <it2s-asn/evcsnm/EvcsnPdu.h>
#include <it2s-asn/evcsnm/EVCSInfo.h>
#include <it2s-asn/itss-transport/BTPPacketIndication.h> #include <it2s-asn/itss-transport/BTPPacketIndication.h>
#include <it2s-tender/epv.h> #include <it2s-tender/epv.h>
#define EVCSNM_INFOS_MAX_LENGTH 16 //MAX number of charging spots
#define POS_HISTORY_MAX_LEN 24 #define POS_HISTORY_MAX_LEN 24
#define PATH_HISTORY_MAX_LEN POS_HISTORY_MAX_LEN-1
enum EVCSNM_CHECK_R { enum EVCSNM_CHECK_R
{
EVCSNM_OK, EVCSNM_OK,
EVCSNM_INVALID, EVCSNM_INVALID,
EVCSNM_BAD_PERMISSIONS EVCSNM_BAD_PERMISSIONS
@ -41,8 +43,22 @@ void* evcsn_service();
*/ */
int evcsnm_check(EvcsnPdu_t *evcsnm); int evcsnm_check(EvcsnPdu_t *evcsnm);
typedef struct evcsnm_args { typedef struct evcs_info {
uint64_t timestamp;
EVCSInfo_t* asn;
} evcs_info_t;
typedef struct evcsnm_args
{
bool activate; bool activate;
struct
{
evcs_info_t *z[EVCSNM_INFOS_MAX_LENGTH];
uint8_t length;
} infos;
} evcsnm_args_t; } evcsnm_args_t;
evcs_info_t* evcs_info_new(EVCSInfo_t* tpi);
void evcs_info_free(evcs_info_t* ti);
#endif #endif

View File

@ -12,49 +12,57 @@
#include <it2s-asn/itss-security/SecurityRequest.h> #include <it2s-asn/itss-security/SecurityRequest.h>
#include <it2s-asn/itss-security/SecurityReply.h> #include <it2s-asn/itss-security/SecurityReply.h>
#include <it2s-asn/tpm/TollingPaymentInfo.h> #include <it2s-asn/tpm/TollingPaymentInfo.h>
#include <it2s-asn/evcsnm/EVCSInfo.h>
#include <it2s-asn/saem/SAEM.h> #include <it2s-asn/saem/SAEM.h>
#include <zmq.h> #include <zmq.h>
SAEM_CODE_R saem_check(SAEM_t *saem, uint8_t *neighbour)
SAEM_CODE_R saem_check(SAEM_t* saem, uint8_t* neighbour) { {
int rv = 0; int rv = 0;
bulletin_t *bulletin = &facilities.bulletin; bulletin_t *bulletin = &facilities.bulletin;
if (saem->header.messageID != messageID_saem) { if (saem->header.messageID != messageID_saem)
{
return SAEM_INVALID_HEADER_MESSAGE_ID; return SAEM_INVALID_HEADER_MESSAGE_ID;
} }
if (saem->header.protocolVersion != 1) { if (saem->header.protocolVersion != 1)
{
return SAEM_INVALID_HEADER_VERSION; return SAEM_INVALID_HEADER_VERSION;
} }
if (bulletin->to_consume_len >= MAX_ANNOUNCEMENTS_LEN - 1) { if (bulletin->to_consume_len >= MAX_ANNOUNCEMENTS_LEN - 1)
{
return SAEM_MAX_ANNOUNCEMENTS_REACHED; return SAEM_MAX_ANNOUNCEMENTS_REACHED;
} }
pthread_mutex_lock(&bulletin->lock); pthread_mutex_lock(&bulletin->lock);
if (saem->sam.body.serviceInfos) { if (saem->sam.body.serviceInfos)
for (int i = 0; i < saem->sam.body.serviceInfos->list.count; ++i) { {
for (int i = 0; i < saem->sam.body.serviceInfos->list.count; ++i)
{
ServiceInfo_t *si = saem->sam.body.serviceInfos->list.array[i]; ServiceInfo_t *si = saem->sam.body.serviceInfos->list.array[i];
uint16_t its_aid = si->serviceID; uint16_t its_aid = si->serviceID;
bool new_announcement = false; bool new_announcement = false;
if (si->chOptions.extensions) { if (si->chOptions.extensions)
{
for (int e = 0; e < si->chOptions.extensions->list.count; ++e) { for (int e = 0; e < si->chOptions.extensions->list.count; ++e)
switch (si->chOptions.extensions->list.array[e]->present) { {
switch (si->chOptions.extensions->list.array[e]->present)
{
case ServiceInfoExt_PR_providerServiceContext: case ServiceInfoExt_PR_providerServiceContext:
bulletin->to_consume[bulletin->to_consume_len]->info.context_len = si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size; bulletin->to_consume[bulletin->to_consume_len]->info.context_len = si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size;
bulletin->to_consume[bulletin->to_consume_len]->info.context = malloc(si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size); bulletin->to_consume[bulletin->to_consume_len]->info.context = malloc(si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size);
memcpy(bulletin->to_consume[bulletin->to_consume_len]->info.context, memcpy(bulletin->to_consume[bulletin->to_consume_len]->info.context,
si->chOptions.extensions->list.array[e]->choice.providerServiceContext.buf, si->chOptions.extensions->list.array[e]->choice.providerServiceContext.buf,
si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size);
);
break; break;
case ServiceInfoExt_PR_applicationDataSAM: case ServiceInfoExt_PR_applicationDataSAM:
@ -62,44 +70,84 @@ SAEM_CODE_R saem_check(SAEM_t* saem, uint8_t* neighbour) {
bulletin->to_consume[bulletin->to_consume_len]->info.data = malloc(si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size); bulletin->to_consume[bulletin->to_consume_len]->info.data = malloc(si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size);
memcpy(bulletin->to_consume[bulletin->to_consume_len]->info.data, memcpy(bulletin->to_consume[bulletin->to_consume_len]->info.data,
si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf, si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf,
si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size);
);
switch (its_aid) { switch (its_aid)
{
case SAID_ETC: case SAID_ETC:
if (facilities.station_type != 15 && facilities.tolling.infos.length < TOLLING_INFOS_MAX_LENGTH) { if (facilities.station_type != 15 && facilities.tolling.infos.length < TOLLING_INFOS_MAX_LENGTH)
{
TollingPaymentInfo_t *tpi = NULL; TollingPaymentInfo_t *tpi = NULL;
asn_dec_rval_t dec = uper_decode_complete( asn_dec_rval_t dec = uper_decode_complete(
NULL, NULL,
&asn_DEF_TollingPaymentInfo, &asn_DEF_TollingPaymentInfo,
(void **)&tpi, (void **)&tpi,
si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf, si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf,
si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size);
); if (!dec.code)
if (!dec.code) { {
bool found = false; bool found = false;
for (int t = 0; t < bulletin->to_consume_len; ++t) { for (int t = 0; t < bulletin->to_consume_len; ++t)
if (((tolling_info_t*)bulletin->to_consume[t]->info.internal_p)->asn->id == tpi->id) { {
if (((tolling_info_t *)bulletin->to_consume[t]->info.internal_p)->asn->id == tpi->id)
{
found = true; found = true;
break; break;
} }
} }
if (!found) { if (!found)
{
facilities.tolling.infos.z[facilities.tolling.infos.length] = tolling_info_new(tpi); facilities.tolling.infos.z[facilities.tolling.infos.length] = tolling_info_new(tpi);
bulletin->to_consume[bulletin->to_consume_len]->info.internal_p = facilities.tolling.infos.z[facilities.tolling.infos.length]; bulletin->to_consume[bulletin->to_consume_len]->info.internal_p = facilities.tolling.infos.z[facilities.tolling.infos.length];
++facilities.tolling.infos.length; ++facilities.tolling.infos.length;
new_announcement = true; new_announcement = true;
} }
} else { }
else
{
ASN_STRUCT_FREE(asn_DEF_TollingPaymentInfo, tpi); ASN_STRUCT_FREE(asn_DEF_TollingPaymentInfo, tpi);
} }
} }
break; break;
case SAID_EVCSN: case SAID_EVCSN:
// TODO if (facilities.station_type != 15 && facilities.evcsnm_args.infos.length < EVCSNM_INFOS_MAX_LENGTH)
{
EVCSInfo_t *evcsi = NULL;
asn_dec_rval_t dec = uper_decode_complete(
NULL,
&asn_DEF_EVCSInfo,
(void **)&evcsi,
si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf,
si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size);
if (!dec.code)
{
bool found = false;
for (int t = 0; t < bulletin->to_consume_len; ++t)
{
if (((evcs_info_t *)bulletin->to_consume[t]->info.internal_p)->asn->id == evcsi->id)
{
found = true;
break;
}
}
if (!found)
{
facilities.evcsnm_args.infos.z[facilities.evcsnm_args.infos.length] = evcs_info_new(evcsi);
bulletin->to_consume[bulletin->to_consume_len]->info.internal_p = facilities.evcsnm_args.infos.z[facilities.evcsnm_args.infos.length];
++facilities.evcsnm_args.infos.length;
new_announcement = true;
}
}
else
{
ASN_STRUCT_FREE(asn_DEF_EVCSInfo, evcsi);
}
}
break; break;
} }
break; break;
@ -121,23 +169,26 @@ SAEM_CODE_R saem_check(SAEM_t* saem, uint8_t* neighbour) {
uint16_t ci_index = si->channelIndex; uint16_t ci_index = si->channelIndex;
// TODO channelInfos // TODO channelInfos
if (saem->sam.body.channelInfos) { if (saem->sam.body.channelInfos)
if (saem->sam.body.channelInfos->list.count >= ci_index + 1) { {
if (saem->sam.body.channelInfos->list.count >= ci_index + 1)
{
} }
} }
if (new_announcement && bulletin->to_consume_len < MAX_ANNOUNCEMENTS_LEN - 1) { if (new_announcement && bulletin->to_consume_len < MAX_ANNOUNCEMENTS_LEN - 1)
{
bulletin->to_consume[bulletin->to_consume_len]->its_aid = its_aid; bulletin->to_consume[bulletin->to_consume_len]->its_aid = its_aid;
bulletin->to_consume[bulletin->to_consume_len]->station_id = saem->header.stationID; bulletin->to_consume[bulletin->to_consume_len]->station_id = saem->header.stationID;
bulletin->to_consume[bulletin->to_consume_len]->timestamp = itss_time_get(); bulletin->to_consume[bulletin->to_consume_len]->timestamp = itss_time_get();
if (neighbour) { if (neighbour)
{
bulletin->to_consume[bulletin->to_consume_len]->certificate_id = malloc(8); bulletin->to_consume[bulletin->to_consume_len]->certificate_id = malloc(8);
memcpy(bulletin->to_consume[bulletin->to_consume_len]->certificate_id, neighbour, 8); memcpy(bulletin->to_consume[bulletin->to_consume_len]->certificate_id, neighbour, 8);
} }
++bulletin->to_consume_len; ++bulletin->to_consume_len;
rv = SAEM_NEW; rv = SAEM_NEW;
} }
} }
} }
@ -146,17 +197,18 @@ SAEM_CODE_R saem_check(SAEM_t* saem, uint8_t* neighbour) {
return rv == SAEM_NEW ? SAEM_NEW : SAEM_OK; return rv == SAEM_NEW ? SAEM_NEW : SAEM_OK;
} }
void bulletin_init() { void bulletin_init()
{
bulletin_t *bulletin = &facilities.bulletin; bulletin_t *bulletin = &facilities.bulletin;
pthread_mutex_init(&bulletin->lock, NULL); pthread_mutex_init(&bulletin->lock, NULL);
bulletin->to_consume_len = 0; bulletin->to_consume_len = 0;
for (int i = 0; i < MAX_ANNOUNCEMENTS_LEN; ++i) { for (int i = 0; i < MAX_ANNOUNCEMENTS_LEN; ++i)
{
bulletin->to_consume[i] = calloc(1, sizeof(announcement_t)); bulletin->to_consume[i] = calloc(1, sizeof(announcement_t));
} }
} }
/** /**
@ -165,11 +217,12 @@ void bulletin_init() {
* @param b_saem_len The encoded SAEM length. * @param b_saem_len The encoded SAEM length.
* @return 0 on success, 1 otherwise. * @return 0 on success, 1 otherwise.
*/ */
static int mk_saem(uint8_t* b_saem, uint32_t* b_saem_len) { static int mk_saem(uint8_t *b_saem, uint32_t *b_saem_len)
{
int rv = 0; int rv = 0;
// Check tolling advertisements // Check tolling advertisements
if (!facilities.tolling.infos.length /* || facilites.evcsn.infos.length */) { if (!facilities.tolling.infos.length && !facilities.evcsnm_args.infos.length)
{
return 1; return 1;
} }
@ -188,13 +241,14 @@ static int mk_saem(uint8_t* b_saem, uint32_t* b_saem_len) {
saem->sam.version = 0; saem->sam.version = 0;
saem->sam.body.serviceInfos = calloc(1, sizeof(ServiceInfos_t)); saem->sam.body.serviceInfos = calloc(1, sizeof(ServiceInfos_t));
saem->sam.body.serviceInfos->list.count = facilities.tolling.infos.length; // + facilities.evcsn.infos.length; saem->sam.body.serviceInfos->list.count = facilities.tolling.infos.length + facilities.evcsnm_args.infos.length;
saem->sam.body.serviceInfos->list.size = facilities.tolling.infos.length * sizeof(void*); // + facilities.evcsn.infos.length * sizeof(void*); saem->sam.body.serviceInfos->list.size = (facilities.tolling.infos.length + facilities.evcsnm_args.infos.length) * sizeof(void *);
saem->sam.body.serviceInfos->list.array = malloc(facilities.tolling.infos.length * sizeof(void*)); // + facilities.evcsn.infos.length * sizeof(void*); saem->sam.body.serviceInfos->list.array = malloc((facilities.tolling.infos.length + facilities.evcsnm_args.infos.length) * sizeof(void *));
uint8_t buf[1024]; uint8_t buf[1024];
int i; int i;
for (i = 0; i < facilities.tolling.infos.length; ++i) { for (i = 0; i < facilities.tolling.infos.length; ++i)
{
saem->sam.body.serviceInfos->list.array[i] = calloc(1, sizeof(ServiceInfo_t)); saem->sam.body.serviceInfos->list.array[i] = calloc(1, sizeof(ServiceInfo_t));
saem->sam.body.serviceInfos->list.array[i]->serviceID = SAID_ETC; saem->sam.body.serviceInfos->list.array[i]->serviceID = SAID_ETC;
@ -202,7 +256,8 @@ static int mk_saem(uint8_t* b_saem, uint32_t* b_saem_len) {
ServiceInfoExts_t *exts = saem->sam.body.serviceInfos->list.array[i]->chOptions.extensions; ServiceInfoExts_t *exts = saem->sam.body.serviceInfos->list.array[i]->chOptions.extensions;
switch (facilities.tolling.protocol.p) { switch (facilities.tolling.protocol.p)
{
case TOLLING_PROTOCOL_SIMPLE: case TOLLING_PROTOCOL_SIMPLE:
exts->list.count = 3; exts->list.count = 3;
exts->list.size = 3 * sizeof(void *); exts->list.size = 3 * sizeof(void *);
@ -225,7 +280,8 @@ static int mk_saem(uint8_t* b_saem, uint32_t* b_saem_len) {
exts->list.array[2]->choice.applicationDataSAM.buf = malloc(1024); exts->list.array[2]->choice.applicationDataSAM.buf = malloc(1024);
enc = uper_encode_to_buffer(&asn_DEF_TollingPaymentInfo, NULL, facilities.tolling.infos.z[i]->asn, exts->list.array[2]->choice.applicationDataSAM.buf, 1024); enc = uper_encode_to_buffer(&asn_DEF_TollingPaymentInfo, NULL, facilities.tolling.infos.z[i]->asn, exts->list.array[2]->choice.applicationDataSAM.buf, 1024);
if (enc.encoded == -1) { if (enc.encoded == -1)
{
log_error("[sa] failure to encode TollingPaymentInfo (%s)", enc.failed_type->name); log_error("[sa] failure to encode TollingPaymentInfo (%s)", enc.failed_type->name);
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -263,7 +319,8 @@ static int mk_saem(uint8_t* b_saem, uint32_t* b_saem_len) {
exts->list.array[3]->choice.applicationDataSAM.buf = malloc(1024); exts->list.array[3]->choice.applicationDataSAM.buf = malloc(1024);
enc = uper_encode_to_buffer(&asn_DEF_TollingPaymentInfo, NULL, facilities.tolling.infos.z[i]->asn, exts->list.array[3]->choice.applicationDataSAM.buf, 1024); enc = uper_encode_to_buffer(&asn_DEF_TollingPaymentInfo, NULL, facilities.tolling.infos.z[i]->asn, exts->list.array[3]->choice.applicationDataSAM.buf, 1024);
if (enc.encoded == -1) { if (enc.encoded == -1)
{
log_error("[sa] failure to encode TollingPaymentInfo (%s)", enc.failed_type->name); log_error("[sa] failure to encode TollingPaymentInfo (%s)", enc.failed_type->name);
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -274,16 +331,48 @@ static int mk_saem(uint8_t* b_saem, uint32_t* b_saem_len) {
} }
} }
for (int j = 0; j < 0/* + facilities.evcsn.infos.length */; ++j) { for (int j = 0; j < facilities.evcsnm_args.infos.length; ++j)
{
saem->sam.body.serviceInfos->list.array[i + j] = calloc(1, sizeof(ServiceInfo_t)); saem->sam.body.serviceInfos->list.array[i + j] = calloc(1, sizeof(ServiceInfo_t));
saem->sam.body.serviceInfos->list.array[i + j]->serviceID = SAID_EVCSN; saem->sam.body.serviceInfos->list.array[i + j]->serviceID = SAID_EVCSN;
// TODO saem->sam.body.serviceInfos->list.array[i + j]->chOptions.extensions = calloc(1, sizeof(ServiceInfoExts_t));
ServiceInfoExts_t *exts = saem->sam.body.serviceInfos->list.array[i + j]->chOptions.extensions;
exts->list.count = 3;
exts->list.size = 3 * sizeof(void *);
exts->list.array = malloc(3 * sizeof(void *));
exts->list.array[0] = calloc(1, sizeof(ServiceInfoExt_t));
exts->list.array[0]->present = ServiceInfoExt_PR_providerServiceContext;
char ctx_s[] = "evcsnm";
exts->list.array[0]->choice.providerServiceContext.size = strlen(ctx_s);
exts->list.array[0]->choice.providerServiceContext.buf = malloc(strlen(ctx_s));
memcpy(exts->list.array[0]->choice.providerServiceContext.buf, ctx_s, strlen(ctx_s));
exts->list.array[1] = calloc(1, sizeof(ServiceInfoExt_t));
exts->list.array[1]->present = ServiceInfoExt_PR_servicePort;
exts->list.array[1]->choice.servicePort = Port_poi;
exts->list.array[2] = calloc(1, sizeof(ServiceInfoExt_t));
exts->list.array[2]->present = ServiceInfoExt_PR_applicationDataSAM;
exts->list.array[2]->choice.applicationDataSAM.buf = malloc(1024);
enc = uper_encode_to_buffer(&asn_DEF_EVCSInfo, NULL, facilities.evcsnm_args.infos.z[i]->asn, exts->list.array[2]->choice.applicationDataSAM.buf, 1024);
if (enc.encoded == -1)
{
log_error("[sa] failure to encode EVCSInfo (%s)", enc.failed_type->name);
rv = 1;
goto cleanup;
}
exts->list.array[2]->choice.applicationDataSAM.size = (enc.encoded + 7) / 8;
} }
pthread_mutex_unlock(&facilities.id.lock); pthread_mutex_unlock(&facilities.id.lock);
enc = asn_encode_to_buffer(NULL, ATS_UNALIGNED_CANONICAL_PER, &asn_DEF_SAEM, saem, b_saem, *b_saem_len); enc = asn_encode_to_buffer(NULL, ATS_UNALIGNED_CANONICAL_PER, &asn_DEF_SAEM, saem, b_saem, *b_saem_len);
if (enc.encoded == -1) { if (enc.encoded == -1)
{
log_error("[sa] failure to encode SAEM (%s)", enc.failed_type->name); log_error("[sa] failure to encode SAEM (%s)", enc.failed_type->name);
rv = 1; rv = 1;
goto cleanup; goto cleanup;
@ -296,7 +385,8 @@ cleanup:
return rv; return rv;
} }
void *sa_service() { void *sa_service()
{
pthread_mutex_init(&facilities.bulletin.lock, NULL); pthread_mutex_init(&facilities.bulletin.lock, NULL);
@ -312,7 +402,8 @@ void *sa_service() {
bpr->btpType = BTPType_btpB; bpr->btpType = BTPType_btpB;
bpr->gn.destinationAddress.buf = malloc(6); bpr->gn.destinationAddress.buf = malloc(6);
for (int i = 0; i < 6; ++i) { for (int i = 0; i < 6; ++i)
{
bpr->gn.destinationAddress.buf[i] = 0xff; bpr->gn.destinationAddress.buf[i] = 0xff;
} }
bpr->gn.destinationAddress.size = 6; bpr->gn.destinationAddress.size = 6;
@ -339,28 +430,36 @@ void *sa_service() {
int sleep_ms = 100; int sleep_ms = 100;
int mk_saem_n_sleep = 0; int mk_saem_n_sleep = 0;
while (!facilities.exit) { while (!facilities.exit)
{
if (bulletin->to_provide_len && sleep_ms*mk_saem_n_sleep >= 1000) { if (bulletin->to_provide_len && sleep_ms * mk_saem_n_sleep >= 1000)
{
rv = mk_saem(bpr->data.buf, (uint32_t *)&bpr->data.size); rv = mk_saem(bpr->data.buf, (uint32_t *)&bpr->data.size);
if (!rv) { if (!rv)
{
bpr->id = itss_id(bpr->data.buf, bpr->data.size); bpr->id = itss_id(bpr->data.buf, bpr->data.size);
asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_TransportRequest, NULL, tr, tr_oer + 1, 1023); asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_TransportRequest, NULL, tr, tr_oer + 1, 1023);
if (enc.encoded == -1) { if (enc.encoded == -1)
{
log_error("encoding TR for SAEM failed"); log_error("encoding TR for SAEM failed");
continue; continue;
} else { }
else
{
itss_queue_send(facilities.tx_queue, tr_oer, enc.encoded + 1, ITSS_TRANSPORT, bpr->id, "TR.packet.btp"); itss_queue_send(facilities.tx_queue, tr_oer, enc.encoded + 1, ITSS_TRANSPORT, bpr->id, "TR.packet.btp");
// Logging // Logging
if (facilities.logging.dbms) { if (facilities.logging.dbms)
{
pthread_mutex_lock(&facilities.id.lock); pthread_mutex_lock(&facilities.id.lock);
uint32_t station_id = facilities.id.station_id; uint32_t station_id = facilities.id.station_id;
pthread_mutex_unlock(&facilities.id.lock); pthread_mutex_unlock(&facilities.id.lock);
itss_db_add(facilities.logging.dbms, station_id, bpr->id, true, messageID_saem, NULL, bpr->data.buf, bpr->data.size); itss_db_add(facilities.logging.dbms, station_id, bpr->id, true, messageID_saem, NULL, bpr->data.buf, bpr->data.size);
} }
if (facilities.logging.recorder) { if (facilities.logging.recorder)
{
uint16_t buffer_len = 2048; uint16_t buffer_len = 2048;
uint8_t buffer[buffer_len]; uint8_t buffer[buffer_len];
int e = itss_management_record_packet_sdu( int e = itss_management_record_packet_sdu(
@ -372,7 +471,8 @@ void *sa_service() {
itss_time_get(), itss_time_get(),
ITSS_FACILITIES, ITSS_FACILITIES,
true); true);
if (e != -1) { if (e != -1)
{
itss_queue_send(facilities.tx_queue, buffer, e, ITSS_MANAGEMENT, bpr->id, "MReq.packet.set"); itss_queue_send(facilities.tx_queue, buffer, e, ITSS_MANAGEMENT, bpr->id, "MReq.packet.set");
} }
} }
@ -392,24 +492,26 @@ void *sa_service() {
uint64_t now = itss_time_get(); uint64_t now = itss_time_get();
pthread_mutex_lock(&bulletin->lock); pthread_mutex_lock(&bulletin->lock);
for (int a = 0; a < bulletin->to_consume_len; ++a) { for (int a = 0; a < bulletin->to_consume_len; ++a)
{
// Tolling // Tolling
if (facilities.tolling.enabled && if (facilities.tolling.enabled &&
bulletin->to_consume[a]->its_aid == 1 && bulletin->to_consume[a]->its_aid == 1 &&
( (now > bulletin->to_consume[a]->t_trigger + TOLLING_PAYMENT_MIN_PERIOD_MS ||
now > bulletin->to_consume[a]->t_trigger + TOLLING_PAYMENT_MIN_PERIOD_MS || (facilities.tolling.protocol.p == TOLLING_PROTOCOL_SIMPLE && tpm_should_retransmit())) &&
(facilities.tolling.protocol.p == TOLLING_PROTOCOL_SIMPLE && tpm_should_retransmit()) facilities.station_type != 15)
) && {
facilities.station_type != 15) {
tolling_info_t *info = (tolling_info_t *)bulletin->to_consume[a]->info.internal_p; tolling_info_t *info = (tolling_info_t *)bulletin->to_consume[a]->info.internal_p;
if (!tpm_is_inside_zone(info)) { if (!tpm_is_inside_zone(info))
{
continue; continue;
} }
switch (facilities.tolling.protocol.p) { switch (facilities.tolling.protocol.p)
{
case TOLLING_PROTOCOL_SIMPLE: case TOLLING_PROTOCOL_SIMPLE:
tpm_pay(info, &security_socket, bulletin->to_consume[a]->certificate_id, NULL); tpm_pay(info, &security_socket, bulletin->to_consume[a]->certificate_id, NULL);
++bulletin->to_consume[a]->n_trigger; ++bulletin->to_consume[a]->n_trigger;
@ -434,7 +536,8 @@ void *sa_service() {
// Tolling management // Tolling management
if (facilities.tolling.protocol.p == TOLLING_PROTOCOL_TLS || if (facilities.tolling.protocol.p == TOLLING_PROTOCOL_TLS ||
facilities.tolling.protocol.p == TOLLING_PROTOCOL_TLS_GN || facilities.tolling.protocol.p == TOLLING_PROTOCOL_TLS_GN ||
facilities.tolling.protocol.p == TOLLING_PROTOCOL_TLS_SHS) { facilities.tolling.protocol.p == TOLLING_PROTOCOL_TLS_SHS)
{
tolling_tlsc_mgmt(facilities.tx_queue, &security_socket); tolling_tlsc_mgmt(facilities.tx_queue, &security_socket);
} }
@ -445,6 +548,5 @@ void *sa_service() {
itss_0close(security_socket); itss_0close(security_socket);
return NULL; return NULL;
} }