577 lines
23 KiB
C
577 lines
23 KiB
C
#include "config.h"
|
|
#include "facilities.h"
|
|
#include "saem.h"
|
|
#include "tpm.h"
|
|
#include "vcm.h"
|
|
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <it2s-config/t2c-itss.h>
|
|
#include <it2s-config/t2c-etsi-its.h>
|
|
#include <dirent.h>
|
|
#include <sys/time.h>
|
|
#include <it2s-asn/etsi-its-sdu/cdd-1.3.1/EIS_ProtectedCommunicationZone.h>
|
|
#include <it2s-asn/etsi-its-v1/tpm/EI1_TollingPaymentInfo.h>
|
|
#include <zmq.h>
|
|
|
|
#include <it2s-tender/packet.h>
|
|
|
|
#include <it2s-asn/etsi-its-sdu/itss-management/EIS_ManagementRequest.h>
|
|
#include <it2s-asn/etsi-its-sdu/itss-management/EIS_ManagementReply.h>
|
|
#include <it2s-asn/etsi-its-sdu/itss-security/EIS_SecurityRequest.h>
|
|
#include <it2s-asn/etsi-its-sdu/itss-security/EIS_SecurityReply.h>
|
|
|
|
static int fetch_target_address(char** addresses, uint16_t addresses_len) {
|
|
int index = -1;
|
|
|
|
for (int i = 0; i < addresses_len; ++i) {
|
|
char* addr = addresses[i];
|
|
|
|
// If TCP, ignore receiver addresses, e.g. tcp://*:[port]
|
|
if (!memcmp(addr, "tcp", 3)) {
|
|
bool found_astk = false;
|
|
for (int j = 0; j < strlen(addr); ++j) {
|
|
if (addr[j] == '*') {
|
|
found_astk = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found_astk) continue;
|
|
}
|
|
|
|
index = i;
|
|
break;
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
int facilities_config() {
|
|
int rv = 0;
|
|
|
|
t2c_itss_t* itss_cfg = NULL;
|
|
t2c_etsi_its_t* etsi_its_cfg = NULL;
|
|
|
|
rv = t2c_itss_read("/etc/it2s/itss.toml", &itss_cfg);
|
|
if (rv) {
|
|
syslog_error("[config] read ITS-S config failed");
|
|
goto cleanup;
|
|
}
|
|
rv = t2c_etsi_its_read("/etc/it2s/etsi-its.toml", &etsi_its_cfg);
|
|
if (rv) {
|
|
syslog_error("[config] read ETSI ITS config failed");
|
|
goto cleanup;
|
|
}
|
|
|
|
// Logging - status messages
|
|
bool use_syslog = false, use_std = false, use_file = false;
|
|
for (int i = 0; i < itss_cfg->general.logging.status_len; ++i) {
|
|
if (!strcmp(itss_cfg->general.logging.status[i], "syslog")) {
|
|
use_syslog = true;
|
|
} else if (!strcmp(itss_cfg->general.logging.status[i], "std")) {
|
|
use_std = true;
|
|
} else if (!strcmp(itss_cfg->general.logging.status[i], "file")) {
|
|
use_file = true;
|
|
}
|
|
}
|
|
log_init(use_syslog, use_std, use_file, "facilities", NULL);
|
|
|
|
itss_0init(&facilities.exit);
|
|
|
|
struct timeval time;
|
|
gettimeofday(&time,NULL);
|
|
srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
|
|
|
|
facilities.zmq.responders = calloc(etsi_its_cfg->facilities.zmq.addresses_len + 1, sizeof(zmq_pollitem_t));
|
|
facilities.zmq.n_responders = 1;
|
|
|
|
// Internal socket
|
|
void* socket = itss_0bind(ZMQ_INTERNAL_ADDR, ZMQ_PAIR);
|
|
facilities.zmq.responders[0].socket = socket;
|
|
facilities.zmq.responders[0].events = ZMQ_POLLIN;
|
|
|
|
for (int i = 0; i < etsi_its_cfg->facilities.zmq.addresses_len; ++i) {
|
|
char* addr = etsi_its_cfg->facilities.zmq.addresses[i];
|
|
|
|
// IPC
|
|
if (!memcmp(addr, "ipc", 3)) {
|
|
|
|
// Create dir
|
|
int lp = 0;
|
|
for (int j = 0; j < strlen(addr); ++j) {
|
|
if (addr[j] == '/') lp = j;
|
|
}
|
|
|
|
char dir[256];
|
|
memcpy(dir, addr+6, lp-6);
|
|
dir[lp-6] = 0;
|
|
|
|
struct stat st = {0};
|
|
if (stat(dir, &st) == -1) {
|
|
mkdir(dir, 0777);
|
|
}
|
|
|
|
// Bind
|
|
void* socket = itss_0bind(addr, ZMQ_REP);
|
|
|
|
facilities.zmq.responders[facilities.zmq.n_responders].socket = socket;
|
|
facilities.zmq.responders[facilities.zmq.n_responders].events = ZMQ_POLLIN;
|
|
++facilities.zmq.n_responders;
|
|
|
|
} else if (!memcmp(addr, "tcp", 3)) {
|
|
|
|
bool found_astk = false;
|
|
for (int j = 0; j < strlen(addr); ++j) {
|
|
if (addr[j] == '*') {
|
|
found_astk = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (found_astk) {
|
|
// Bind
|
|
void* socket = itss_0bind(addr, ZMQ_REP);
|
|
|
|
facilities.zmq.responders[facilities.zmq.n_responders].socket = socket;
|
|
facilities.zmq.responders[facilities.zmq.n_responders].events = ZMQ_POLLIN;
|
|
++facilities.zmq.n_responders;
|
|
}
|
|
}
|
|
}
|
|
if (facilities.zmq.n_responders <= 1) {
|
|
log_info("[config] a valid address to listen to was not found, exiting now");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Fetch [networking] address
|
|
int index = fetch_target_address(etsi_its_cfg->networking.zmq.addresses, etsi_its_cfg->networking.zmq.addresses_len);
|
|
if (index != -1) {
|
|
facilities.zmq.networking_address = malloc(strlen(etsi_its_cfg->networking.zmq.addresses[index])+1);
|
|
strcpy(facilities.zmq.networking_address, etsi_its_cfg->networking.zmq.addresses[index]);
|
|
} else {
|
|
log_error("[config] a valid address for [networking] was not found");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
// Fetch [applications] address
|
|
index = fetch_target_address(itss_cfg->applications.zmq.addresses, itss_cfg->applications.zmq.addresses_len);
|
|
if (index != -1) {
|
|
facilities.zmq.applications_address = malloc(strlen(itss_cfg->applications.zmq.addresses[index])+1);
|
|
strcpy(facilities.zmq.applications_address, itss_cfg->applications.zmq.addresses[index]);
|
|
} else {
|
|
log_error("[config] a valid address for [applications] was not found");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Fetch [security] address
|
|
index = fetch_target_address(itss_cfg->security.zmq.addresses, itss_cfg->security.zmq.addresses_len);
|
|
if (index != -1) {
|
|
facilities.zmq.security_address = malloc(strlen(itss_cfg->security.zmq.addresses[index])+1);
|
|
strcpy(facilities.zmq.security_address, itss_cfg->security.zmq.addresses[index]);
|
|
} else {
|
|
log_error("[config] a valid address for [security] was not found");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Fetch [management] address
|
|
index = fetch_target_address(etsi_its_cfg->management.zmq.addresses, etsi_its_cfg->management.zmq.addresses_len);
|
|
if (index != -1) {
|
|
facilities.zmq.management_address = malloc(strlen(etsi_its_cfg->management.zmq.addresses[index])+1);
|
|
strcpy(facilities.zmq.management_address, etsi_its_cfg->management.zmq.addresses[index]);
|
|
} else {
|
|
log_error("[config] a valid address for [management] was not found");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
// Values
|
|
// General
|
|
if (!strcmp("obu", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 5;
|
|
} else if (!strcmp("rsu", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 15;
|
|
} else if (!strcmp("unknown", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 0;
|
|
} else if (!strcmp("pedestrian", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 1;
|
|
} else if (!strcmp("cyclist", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 2;
|
|
} else if (!strcmp("moped", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 3;
|
|
} else if (!strcmp("motorcycle", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 4;
|
|
} else if (!strcmp("passengerCar", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 5;
|
|
} else if (!strcmp("bus", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 6;
|
|
} else if (!strcmp("lightTruck", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 7;
|
|
} else if (!strcmp("heavyTruck", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 8;
|
|
} else if (!strcmp("trailer", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 9;
|
|
} else if (!strcmp("specialVehicles", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 10;
|
|
} else if (!strcmp("tram", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 11;
|
|
} else if (!strcmp("roadSideUnit", itss_cfg->general.itss_type)) {
|
|
facilities.station_type = 15;
|
|
} else {
|
|
log_error("[config] unrecognized ITS-S type, running as OBU");
|
|
facilities.station_type = 5;
|
|
}
|
|
|
|
|
|
facilities.use_security = itss_cfg->security.use_security;
|
|
|
|
pthread_mutex_init(&facilities.id.lock, NULL);
|
|
pthread_mutex_init(&facilities.id.change.lock, NULL);
|
|
|
|
facilities.id.change.random = itss_cfg->security.identity.random;
|
|
if (facilities.id.change.random) {
|
|
// Ask [security] for station id
|
|
|
|
EIS_SecurityRequest_t* sREQ = calloc(1, sizeof(EIS_SecurityRequest_t));
|
|
EIS_SecurityReply_t* sREP = NULL;
|
|
|
|
sREQ->present = EIS_SecurityRequest_PR_ids;
|
|
sREQ->choice.ids.list.count = 2;
|
|
sREQ->choice.ids.list.size = 2*sizeof(void*);
|
|
sREQ->choice.ids.list.array = malloc(2*sizeof(void*));
|
|
sREQ->choice.ids.list.array[0] = calloc(1, sizeof(EIS_SecurityIdType_t));
|
|
*sREQ->choice.ids.list.array[0] = EIS_SecurityIdType_stationId;
|
|
sREQ->choice.ids.list.array[1] = calloc(1, sizeof(EIS_SecurityIdType_t));
|
|
*sREQ->choice.ids.list.array[1] = EIS_SecurityIdType_ipv6Address;
|
|
|
|
uint8_t b_tx[256], b_rx[256];
|
|
asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_EIS_SecurityRequest, NULL, sREQ, b_tx, 256);
|
|
|
|
void* ss = itss_0connect(facilities.zmq.security_address, ZMQ_REQ);
|
|
itss_0send(ss, b_tx, enc.encoded);
|
|
int rl = itss_0recv_rt(&ss, b_rx, 256, b_tx, 256, -1);
|
|
itss_0close(ss);
|
|
if (rl == -1) {
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
asn_dec_rval_t dec = oer_decode(NULL, &asn_DEF_EIS_SecurityReply, (void**) &sREP, b_rx, 256);
|
|
|
|
if (sREP->returnCode == EIS_SecurityReplyReturnCode_rejected) {
|
|
// TODO handle it
|
|
goto cleanup;
|
|
}
|
|
|
|
for (int i = 0; i < sREP->data->choice.ids.list.count; ++i) {
|
|
switch (sREP->data->choice.ids.list.array[i]->present) {
|
|
case EIS_SecurityId_PR_stationId:
|
|
facilities.id.station_id = sREP->data->choice.ids.list.array[i]->choice.stationId;
|
|
break;
|
|
case EIS_SecurityId_PR_ipv6Address:
|
|
memcpy(facilities.id.ipv6_addr, sREP->data->choice.ids.list.array[i]->choice.ipv6Address.buf, 16);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASN_STRUCT_FREE(asn_DEF_EIS_SecurityRequest, sREQ);
|
|
ASN_STRUCT_FREE(asn_DEF_EIS_SecurityReply, sREP);
|
|
|
|
} else {
|
|
facilities.id.station_id = itss_cfg->security.identity.station_id;
|
|
|
|
uint8_t src_mac[6];
|
|
unsigned int tmp_uint[6];
|
|
|
|
sscanf(itss_cfg->security.identity.mac_address, "%02x:%02x:%02x:%02x:%02x:%02x",
|
|
&tmp_uint[0],
|
|
&tmp_uint[1],
|
|
&tmp_uint[2],
|
|
&tmp_uint[3],
|
|
&tmp_uint[4],
|
|
&tmp_uint[5]);
|
|
|
|
src_mac[0] = (uint8_t)tmp_uint[0];
|
|
src_mac[1] = (uint8_t)tmp_uint[1];
|
|
src_mac[2] = (uint8_t)tmp_uint[2];
|
|
src_mac[3] = (uint8_t)tmp_uint[3];
|
|
src_mac[4] = (uint8_t)tmp_uint[4];
|
|
src_mac[5] = (uint8_t)tmp_uint[5];
|
|
|
|
memset(facilities.id.ipv6_addr, 0, 8);
|
|
memcpy(facilities.id.ipv6_addr+8, src_mac, 3);
|
|
facilities.id.ipv6_addr[11] = 0xff;
|
|
facilities.id.ipv6_addr[12] = 0xfe;
|
|
memcpy(facilities.id.ipv6_addr+13, src_mac+3, 3);
|
|
facilities.id.ipv6_addr[8] ^= 0x02;
|
|
}
|
|
|
|
// Message version
|
|
if (!strcmp("v1", etsi_its_cfg->facilities.mver.default_version)) {
|
|
log_error("[config] only default message version 2 is supported");
|
|
return -1;
|
|
} else if (!strcmp("v2", etsi_its_cfg->facilities.mver.default_version)) {
|
|
facilities.pver.defaultv = 2;
|
|
} else {
|
|
log_warn("[config] unrecognized default messages version :: using version 2");
|
|
facilities.pver.defaultv = 2;
|
|
}
|
|
|
|
// DENM
|
|
facilities.den.n_max_events = etsi_its_cfg->facilities.denm.nmax_active_events;
|
|
|
|
// CAM
|
|
facilities.lightship.active = etsi_its_cfg->facilities.cam.activate;
|
|
facilities.lightship.vehicle_gen_min = etsi_its_cfg->facilities.cam.obu_period_min;
|
|
facilities.lightship.vehicle_gen_max = etsi_its_cfg->facilities.cam.obu_period_max;
|
|
facilities.lightship.rsu_gen_min = etsi_its_cfg->facilities.cam.rsu_period_min;
|
|
facilities.lightship.rsu_vehicle_permanence = etsi_its_cfg->facilities.cam.rsu_vehicle_permanence;
|
|
|
|
// IVIM
|
|
facilities.infrastructure.n_max_services = etsi_its_cfg->facilities.ivim.nmax_active_services;
|
|
facilities.infrastructure.replay_interval = etsi_its_cfg->facilities.ivim.replay_interval;
|
|
facilities.infrastructure.default_service_duration = etsi_its_cfg->facilities.ivim.default_service_duration * 60000;
|
|
|
|
// CPM
|
|
facilities.dissemination.active = etsi_its_cfg->facilities.cpm.activate;
|
|
facilities.dissemination.T_GenCpmMin = etsi_its_cfg->facilities.cpm.rsu_obu_period_min;
|
|
facilities.dissemination.T_GenCpmMax = etsi_its_cfg->facilities.cpm.rsu_obu_period_max;
|
|
// Rotation not needed anymore?
|
|
//facilities.dissemination.radar_rotation = itss_cfg->radar.radar_rotation;
|
|
facilities.dissemination.tmc_connect = etsi_its_cfg->facilities.cpm.tmc_connected;
|
|
facilities.dissemination.T_AddSensorInformation = 1000;
|
|
int oa_start = (360-facilities.dissemination.radar_rotation) * 10 - 500;
|
|
int oa_end = (360-facilities.dissemination.radar_rotation) * 10 + 500;
|
|
facilities.dissemination.opening_angle_start = (oa_start + 3600) % 3600;
|
|
facilities.dissemination.opening_angle_end = (oa_end + 3600) % 3600;
|
|
|
|
facilities.dissemination.int_radar = malloc(strlen(etsi_its_cfg->facilities.cpm.radar_interface)+1);
|
|
strcpy(facilities.dissemination.int_radar,etsi_its_cfg->facilities.cpm.radar_interface);
|
|
facilities.dissemination.ip_radar = malloc(strlen(etsi_its_cfg->facilities.cpm.radar_ip)+1);
|
|
strcpy(facilities.dissemination.ip_radar,etsi_its_cfg->facilities.cpm.radar_ip);
|
|
|
|
// TPM
|
|
facilities.tolling.enabled = etsi_its_cfg->facilities.tpm.activate;
|
|
if (!strcmp("gn-spki", etsi_its_cfg->facilities.tpm.protocol)) {
|
|
facilities.tolling.protocol.p = TOLLING_PROTOCOL_GN_SPKI;
|
|
} else if (!strcmp("gn-dpki", etsi_its_cfg->facilities.tpm.protocol)) {
|
|
facilities.tolling.protocol.p = TOLLING_PROTOCOL_GN_DPKI;
|
|
} else if (!strcmp("tls", etsi_its_cfg->facilities.tpm.protocol)) {
|
|
facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS;
|
|
} else if (!strcmp("tls-gn", etsi_its_cfg->facilities.tpm.protocol)) {
|
|
facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS_GN;
|
|
} else if (!strcmp("tls-shs", etsi_its_cfg->facilities.tpm.protocol)) {
|
|
facilities.tolling.protocol.p = TOLLING_PROTOCOL_TLS_SHS;
|
|
} else {
|
|
log_error("[config] unrecognized tolling protocol, defaulting to 'gn-spki'");
|
|
facilities.tolling.protocol.p = TOLLING_PROTOCOL_GN_SPKI;
|
|
}
|
|
facilities.tolling.station.obu.client_id = etsi_its_cfg->facilities.tpm.client_id;
|
|
|
|
// MCM
|
|
facilities.coordination.active = etsi_its_cfg->facilities.mcm.activate;
|
|
if (!strcmp("vcm-RR", etsi_its_cfg->facilities.mcm.protocol)) {
|
|
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR;
|
|
} else if (!strcmp("vcm-RR1C", etsi_its_cfg->facilities.mcm.protocol)) {
|
|
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR1C;
|
|
} else if (!strcmp("vcm-RRAC", etsi_its_cfg->facilities.mcm.protocol)) {
|
|
facilities.coordination.protocol = MC_PROTOCOL_VCM_RRAC;
|
|
} else {
|
|
facilities.coordination.protocol = MC_PROTOCOL_VCM_RR;
|
|
}
|
|
facilities.coordination.vcm_period_min = etsi_its_cfg->facilities.mcm.period_min;
|
|
facilities.coordination.vcm_period_max = etsi_its_cfg->facilities.mcm.period_max;
|
|
|
|
// EVCSNM
|
|
facilities.evm_args.activate = etsi_its_cfg->facilities.evcsnm.activate;
|
|
|
|
// Replay
|
|
facilities.replay = etsi_its_cfg->networking.replay.activate;
|
|
|
|
// Forward unknown packets (in-stack)
|
|
facilities.upf = etsi_its_cfg->general.unknown_packet_forwarding;
|
|
|
|
// PZ
|
|
if (facilities.station_type == 15) {
|
|
|
|
int i = 0;
|
|
|
|
DIR *d = opendir(etsi_its_cfg->facilities.protected_zones.path);
|
|
struct dirent *dir;
|
|
char file[256];
|
|
char pz_xml[2048];
|
|
if (d) {
|
|
while ((dir = readdir(d)) != NULL && i < 16) {
|
|
if (dir->d_name[0] == '.') continue;
|
|
sprintf(file, "%s/%s", etsi_its_cfg->facilities.protected_zones.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(pz_xml, 1, size, fp)) {
|
|
fclose(fp);
|
|
continue;
|
|
}
|
|
fclose(fp);
|
|
|
|
EIS_ProtectedCommunicationZone_t *zone = calloc(1, sizeof(EIS_ProtectedCommunicationZone_t));
|
|
|
|
asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_EIS_ProtectedCommunicationZone, (void**) &zone, pz_xml, size);
|
|
if (!dec.code) {
|
|
facilities.lightship.protected_zones.pz[i] = (EI1_ProtectedCommunicationZone_t*)zone;
|
|
++facilities.lightship.protected_zones.pz_len;
|
|
++i;
|
|
log_debug("[config] loaded protection zone @ (%lld, %lld)", zone->protectedZoneLatitude, zone->protectedZoneLongitude);
|
|
} else {
|
|
log_error("[config] failure to decode protection zone '%s'", dir->d_name);
|
|
ASN_STRUCT_FREE(asn_DEF_EIS_ProtectedCommunicationZone, zone);
|
|
}
|
|
|
|
}
|
|
closedir(d);
|
|
}
|
|
}
|
|
|
|
// TZ
|
|
if (facilities.station_type == 15) {
|
|
|
|
int i = 0;
|
|
|
|
DIR *d = opendir(etsi_its_cfg->facilities.tpm.tis_path);
|
|
struct dirent *dir;
|
|
char file[256];
|
|
char ti_xml[2048];
|
|
if (d) {
|
|
while ((dir = readdir(d)) != NULL && i < TOLLING_INFOS_MAX_LENGTH) {
|
|
if (dir->d_name[0] == '.') continue;
|
|
sprintf(file, "%s/%s", etsi_its_cfg->facilities.tpm.tis_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);
|
|
|
|
EI1_TollingPaymentInfo_t *ti = calloc(1, sizeof(EI1_TollingPaymentInfo_t));
|
|
|
|
asn_dec_rval_t dec = xer_decode(NULL, &asn_DEF_EI1_TollingPaymentInfo, (void**) &ti, ti_xml, size);
|
|
if (!dec.code) {
|
|
facilities.tolling.infos.z[i] = calloc(1, sizeof(tolling_info_t));
|
|
facilities.tolling.infos.z[i]->asn = ti;
|
|
++facilities.tolling.infos.length;
|
|
++i;
|
|
log_debug("[config] loaded tolling info | id:%lld type:%s",
|
|
ti->id,
|
|
ti->tollType==EI1_TollType_entry ? "entry": ti->tollType==EI1_TollType_exit ? "exit": "single"
|
|
);
|
|
} else {
|
|
log_error("[config] failure to decode tolling info '%s'", dir->d_name);
|
|
ASN_STRUCT_FREE(asn_DEF_EI1_TollingPaymentInfo, ti);
|
|
}
|
|
|
|
}
|
|
closedir(d);
|
|
}
|
|
}
|
|
|
|
|
|
facilities.edm.enabled = itss_cfg->applications.extensions.enabled;
|
|
|
|
EIS_ManagementRequest_t* mreq = calloc(1, sizeof(EIS_ManagementRequest_t));
|
|
mreq->present = EIS_ManagementRequest_PR_attributes;
|
|
mreq->choice.attributes.present = EIS_ManagementRequestAttributes_PR_get;
|
|
mreq->choice.attributes.choice.get.clockType = 1;
|
|
mreq->choice.attributes.choice.get.clockOffset = 1;
|
|
void* management_socket = itss_0connect(facilities.zmq.management_address, ZMQ_REQ);
|
|
uint8_t b_tx[256], b_rx[256];
|
|
asn_enc_rval_t enc = oer_encode_to_buffer(&asn_DEF_EIS_ManagementRequest, NULL, mreq, b_tx, 256);
|
|
|
|
itss_0send(management_socket, b_tx, enc.encoded);
|
|
int rl = itss_0recv_rt(&management_socket, b_rx, 256, b_tx, 256, -1);
|
|
itss_0close(management_socket);
|
|
if (rl == -1) {
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
|
|
EIS_ManagementReply_t* mrep = calloc(1, sizeof(EIS_ManagementReply_t));
|
|
oer_decode(NULL, &asn_DEF_EIS_ManagementReply, (void**) &mrep, b_rx, 256);
|
|
long lat, lon, alt, alt_conf;
|
|
if (mrep->returnCode == EIS_ManagementReplyReturnCode_accepted &&
|
|
mrep->data &&
|
|
mrep->data->choice.attributes.clockType &&
|
|
mrep->data->choice.attributes.clockOffset) {
|
|
|
|
itss_epv_init(*mrep->data->choice.attributes.clockType, TIME_MILLISECONDS, itss_cfg->time.simulated.source);
|
|
|
|
asn_INTEGER2uint64(mrep->data->choice.attributes.clockOffset, &epv.time.offset);
|
|
} else {
|
|
log_error("rejected MR attribute request");
|
|
rv = 1;
|
|
goto cleanup;
|
|
}
|
|
ASN_STRUCT_FREE(asn_DEF_EIS_ManagementRequest, mreq);
|
|
ASN_STRUCT_FREE(asn_DEF_EIS_ManagementReply, mrep);
|
|
|
|
|
|
if (etsi_its_cfg->facilities.saem.activate) { // TODO handle various services
|
|
facilities.bulletin.to_provide_len = 1;
|
|
facilities.bulletin.to_provide[0] = calloc(1, sizeof(announcement_t));
|
|
facilities.bulletin.to_provide[0]->endpoint.port = 7010 + etsi_its_cfg->facilities.saem.service_to_advertise;
|
|
facilities.bulletin.to_provide[0]->its_aid = etsi_its_cfg->facilities.saem.service_to_advertise;
|
|
}
|
|
|
|
facilities.vehicle.length = itss_cfg->vehicle.length;
|
|
facilities.vehicle.width = itss_cfg->vehicle.width;
|
|
facilities.vehicle.role = itss_cfg->vehicle.role;
|
|
|
|
// Logging
|
|
facilities.logging.recorder = etsi_its_cfg->facilities.logging.management;
|
|
if (itss_cfg->general.logging.enabled && etsi_its_cfg->facilities.logging.dbms) {
|
|
facilities.logging.dbms = calloc(1, sizeof(itss_db_t));
|
|
if (itss_db_init(
|
|
facilities.logging.dbms,
|
|
itss_cfg->general.logging.database,
|
|
itss_cfg->general.logging.table_style,
|
|
ITSS_FACILITIES,
|
|
itss_cfg->general.logging.host,
|
|
itss_cfg->general.logging.port,
|
|
itss_cfg->general.logging.username,
|
|
itss_cfg->general.logging.password
|
|
)) {
|
|
log_error("failed to initialize the database -> turning off logging");
|
|
free(facilities.logging.dbms);
|
|
facilities.logging.dbms = NULL;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
t2c_itss_free(itss_cfg);
|
|
t2c_etsi_its_free(etsi_its_cfg);
|
|
|
|
return rv;
|
|
}
|
|
|