denm: Handle 2.1.1 messages

This commit is contained in:
emanuel 2024-03-19 11:21:54 +00:00
parent 7a51c6a5b7
commit 117ed93e31
4 changed files with 151 additions and 44 deletions

View File

@ -36,6 +36,7 @@ TARGET_LINK_LIBRARIES(it2s-itss-facilities
-lit2s-asn-etsi-its-v1-evrsrm
-lit2s-asn-etsi-its-v2-cdd-2.2.1
-lit2s-asn-etsi-its-v2-cam
-lit2s-asn-etsi-its-v2-denm
-lit2s-tender
-lm
-lrt

View File

@ -6,6 +6,8 @@
#include <it2s-tender/time.h>
#include <it2s-tender/space.h>
#define DENM_VERSION(denm) (((EI1_ItsPduHeader_t*)(denm))->protocolVersion)
const cc_ssp_bm_t CC_SSP_BM_MAP[] = {
{"trafficCondition", 1, 0x80000000},
{"accident", 2, 0x40000000},
@ -67,29 +69,56 @@ static int permissions_check(int cause_code, uint8_t* permissions, uint8_t permi
}
static enum EVENT_CHECK_R event_check(EI1_DENM_t *denm, uint8_t* ssp, uint32_t ssp_len) {
static enum EVENT_CHECK_R event_check(void *denm, uint8_t* ssp, uint32_t ssp_len) {
int rv = 0;
den_t* den = &facilities.den;
uint8_t cause_code;
uint32_t action_id_origin_station;
uint32_t action_id_seq_num;
switch (DENM_VERSION(denm)) {
case 1:
;
EI1_DENM_t* denm_v1 = (EI1_DENM_t*) denm;
cause_code = denm_v1->denm.situation->eventType.causeCode;
action_id_origin_station = denm_v1->denm.management.actionID.originatingStationID;
action_id_seq_num = denm_v1->denm.management.actionID.sequenceNumber;
break;
case 2:
;
EI2_DENM_t* denm_v2 = (EI2_DENM_t*) denm;
cause_code = denm_v2->denm.situation->eventType.ccAndScc.present - 1;
action_id_origin_station = denm_v2->denm.management.actionId.originatingStationId;
action_id_seq_num = denm_v2->denm.management.actionId.sequenceNumber;
break;
default:
return EVENT_INVALID;
}
/* Common fields in version 1, 2 */
EI2_DENM_t* denm_c = (EI2_DENM_t*) denm;
uint64_t e_detection_time, e_reference_time;
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.detectionTime, &e_detection_time);
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.referenceTime, &e_reference_time);
asn_INTEGER2ulong((INTEGER_t*) &denm_c->denm.management.detectionTime, &e_detection_time);
asn_INTEGER2ulong((INTEGER_t*) &denm_c->denm.management.referenceTime, &e_reference_time);
if (e_detection_time > e_reference_time) {
return EVENT_INVALID;
}
// Check if event cause code type is permitted by the issuing ticket
if (ssp && denm->denm.situation) {
if (!permissions_check(denm->denm.situation->eventType.causeCode, ssp, ssp_len)) {
if (ssp && denm_c->denm.situation) {
if (!permissions_check(cause_code, ssp, ssp_len)) {
return EVENT_BAD_PERMISSIONS;
}
}
uint32_t e_validity_duration;
if (denm->denm.management.validityDuration != NULL) {
e_validity_duration = *(uint32_t *) denm->denm.management.validityDuration * 1000; // validityDuration comes in seconds
if (denm_c->denm.management.validityDuration != NULL) {
e_validity_duration = *(uint32_t *) denm_c->denm.management.validityDuration * 1000; // validityDuration comes in seconds
} else {
e_validity_duration = 600 * 1000;
}
@ -108,8 +137,8 @@ static enum EVENT_CHECK_R event_check(EI1_DENM_t *denm, uint8_t* ssp, uint32_t s
for (int i = 0; i < den->n_max_events; ++i) {
if (den->events[i]->enabled) {
if (den->events[i]->station_id == denm->denm.management.actionID.originatingStationID &&
den->events[i]->sn == denm->denm.management.actionID.sequenceNumber) {
if (den->events[i]->station_id == action_id_origin_station &&
den->events[i]->sn == action_id_seq_num) {
is_new = false;
@ -133,10 +162,10 @@ static enum EVENT_CHECK_R event_check(EI1_DENM_t *denm, uint8_t* ssp, uint32_t s
if (is_update) {
if (denm->denm.management.termination != NULL) {
if (*denm->denm.management.termination == 0) {
if (denm_c->denm.management.termination != NULL) {
if (*denm_c->denm.management.termination == 0) {
return EVENT_CANCELLATION;
} else if (*denm->denm.management.termination == 1) {
} else if (*denm_c->denm.management.termination == 1) {
return EVENT_NEGATION;
}
}
@ -155,18 +184,44 @@ static enum EVENT_CHECK_R event_check(EI1_DENM_t *denm, uint8_t* ssp, uint32_t s
return EVENT_NEW;
}
static int event_add(EI1_DENM_t *denm, uint64_t* id) {
static int event_add(void *denm, uint64_t* id) {
den_t* den = &facilities.den;
uint64_t now = itss_time_get();
uint8_t cause_code;
uint32_t action_id_origin_station;
uint32_t action_id_seq_num;
switch (DENM_VERSION(denm)) {
case 1:
;
EI1_DENM_t* denm_v1 = (EI1_DENM_t*) denm;
cause_code = denm_v1->denm.situation->eventType.causeCode;
action_id_origin_station = denm_v1->denm.management.actionID.originatingStationID;
action_id_seq_num = denm_v1->denm.management.actionID.sequenceNumber;
break;
case 2:
;
EI2_DENM_t* denm_v2 = (EI2_DENM_t*) denm;
cause_code = denm_v2->denm.situation->eventType.ccAndScc.present - 1;
action_id_origin_station = denm_v2->denm.management.actionId.originatingStationId;
action_id_seq_num = denm_v2->denm.management.actionId.sequenceNumber;
break;
default:
return EVENT_INVALID;
}
/* Common fields in version 1, 2 */
EI2_DENM_t* denm_c = (EI2_DENM_t*) denm;
uint64_t e_detection_time, e_reference_time;
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.detectionTime, &e_detection_time);
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.referenceTime, &e_reference_time);
asn_INTEGER2ulong((INTEGER_t*) &denm_c->denm.management.detectionTime, &e_detection_time);
asn_INTEGER2ulong((INTEGER_t*) &denm_c->denm.management.referenceTime, &e_reference_time);
uint32_t e_validity_duration;
if (denm->denm.management.validityDuration != NULL) {
e_validity_duration = *(uint32_t *) denm->denm.management.validityDuration * 1000; // validityDuration comes in seconds
if (denm_c->denm.management.validityDuration != NULL) {
e_validity_duration = *(uint32_t *) denm_c->denm.management.validityDuration * 1000; // validityDuration comes in seconds
} else {
e_validity_duration = 600 * 1000;
}
@ -182,10 +237,10 @@ static int event_add(EI1_DENM_t *denm, uint64_t* id) {
}
uint8_t state = EVENT_ACTIVE;
if (denm->denm.management.termination != NULL) {
if (*(denm->denm.management.termination) == 0) {
if (denm_c->denm.management.termination != NULL) {
if (*(denm_c->denm.management.termination) == 0) {
state = EVENT_CANCELLED;
} else if (*(denm->denm.management.termination) == 1) {
} else if (*(denm_c->denm.management.termination) == 1) {
state = EVENT_NEGATED;
}
}
@ -206,17 +261,17 @@ static int event_add(EI1_DENM_t *denm, uint64_t* id) {
den->events[index]->id = *id;
den->events[index]->enabled = true;
den->events[index]->state = state;
den->events[index]->station_id = denm->denm.management.actionID.originatingStationID;
den->events[index]->sn = denm->denm.management.actionID.sequenceNumber;
den->events[index]->station_id = action_id_origin_station;
den->events[index]->sn = action_id_seq_num;
den->events[index]->detection_time = e_detection_time;
den->events[index]->reference_time = e_reference_time;
den->events[index]->expiration_time = e_detection_time + e_validity_duration;
den->events[index]->latitude = denm->denm.management.eventPosition.latitude;
den->events[index]->longitude = denm->denm.management.eventPosition.longitude;
den->events[index]->latitude = denm_c->denm.management.eventPosition.latitude;
den->events[index]->longitude = denm_c->denm.management.eventPosition.longitude;
den->events[index]->denm = denm;
if (denm->denm.management.actionID.sequenceNumber > den->sn) {
den->sn = denm->denm.management.actionID.sequenceNumber;
if (action_id_seq_num > den->sn) {
den->sn = action_id_seq_num;
}
}
@ -226,20 +281,46 @@ static int event_add(EI1_DENM_t *denm, uint64_t* id) {
else return 0; // Event added to db
}
static int event_update(EI1_DENM_t *denm, uint64_t* id) {
static int event_update(void *denm, uint64_t* id) {
den_t* den = &facilities.den;
uint64_t now = itss_time_get();
uint8_t cause_code;
uint32_t action_id_origin_station;
uint32_t action_id_seq_num;
switch (DENM_VERSION(denm)) {
case 1:
;
EI1_DENM_t* denm_v1 = (EI1_DENM_t*) denm;
cause_code = denm_v1->denm.situation->eventType.causeCode;
action_id_origin_station = denm_v1->denm.management.actionID.originatingStationID;
action_id_seq_num = denm_v1->denm.management.actionID.sequenceNumber;
break;
case 2:
;
EI2_DENM_t* denm_v2 = (EI2_DENM_t*) denm;
cause_code = denm_v2->denm.situation->eventType.ccAndScc.present - 1;
action_id_origin_station = denm_v2->denm.management.actionId.originatingStationId;
action_id_seq_num = denm_v2->denm.management.actionId.sequenceNumber;
break;
default:
return EVENT_INVALID;
}
/* Common fields in version 1, 2 */
EI2_DENM_t* denm_c = (EI2_DENM_t*) denm;
uint64_t e_detection_time, e_reference_time;
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.detectionTime, &e_detection_time);
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.referenceTime, &e_reference_time);
asn_INTEGER2ulong((INTEGER_t*) &denm_c->denm.management.detectionTime, &e_detection_time);
asn_INTEGER2ulong((INTEGER_t*) &denm_c->denm.management.referenceTime, &e_reference_time);
uint8_t state = EVENT_ACTIVE;
if (denm->denm.management.termination != NULL) {
if (*(denm->denm.management.termination) == 0) {
if (denm_c->denm.management.termination != NULL) {
if (*(denm_c->denm.management.termination) == 0) {
state = EVENT_CANCELLED;
} else if (*(denm->denm.management.termination) == 1) {
} else if (*(denm_c->denm.management.termination) == 1) {
state = EVENT_NEGATED;
}
}
@ -249,8 +330,8 @@ static int event_update(EI1_DENM_t *denm, uint64_t* id) {
for (int i = 0; i < den->n_max_events; ++i) {
if (den->events[i]->enabled) {
if (den->events[i]->station_id == denm->denm.management.actionID.originatingStationID &&
den->events[i]->sn == denm->denm.management.actionID.sequenceNumber) {
if (den->events[i]->station_id == action_id_origin_station &&
den->events[i]->sn == action_id_seq_num) {
index = i;
break;
@ -289,16 +370,16 @@ static int event_update(EI1_DENM_t *denm, uint64_t* id) {
den->events[index]->detection_time = e_detection_time;
den->events[index]->reference_time = e_reference_time;
if (denm->denm.management.validityDuration != NULL) {
den->events[index]->expiration_time = e_detection_time + *(uint32_t *) denm->denm.management.validityDuration * 1000;
if (denm_c->denm.management.validityDuration != NULL) {
den->events[index]->expiration_time = e_detection_time + *(uint32_t *) denm_c->denm.management.validityDuration * 1000;
}
if (state == EVENT_CANCELLED || state == EVENT_NEGATED) { // Keep terminated events for 10 mins
den->events[index]->expiration_time = now + 600 * 1000;
}
den->events[index]->latitude = denm->denm.management.eventPosition.latitude;
den->events[index]->longitude = denm->denm.management.eventPosition.longitude;
den->events[index]->latitude = denm_c->denm.management.eventPosition.latitude;
den->events[index]->longitude = denm_c->denm.management.eventPosition.longitude;
ASN_STRUCT_FREE(asn_DEF_EI1_DENM, den->events[index]->denm);
den->events[index]->denm = denm;
@ -310,7 +391,7 @@ static int event_update(EI1_DENM_t *denm, uint64_t* id) {
else return 0; // Event updated
}
enum EVENT_CHECK_R event_manage(EI1_DENM_t *denm, uint64_t* id, uint8_t* ssp, uint32_t ssp_len) {
enum EVENT_CHECK_R event_manage(void *denm, uint64_t* id, uint8_t* ssp, uint32_t ssp_len) {
int rv = 0;
switch (rv = event_check(denm, ssp, ssp_len)) {
case EVENT_NEW:

View File

@ -3,6 +3,7 @@
#include <stdint.h>
#include <it2s-asn/etsi-its-v1/denm/EI1_DENM.h>
#include <it2s-asn/etsi-its-v2/denm/EI2_DENM.h>
#include <pthread.h>
#include <stdbool.h>
@ -16,7 +17,7 @@ enum EVENT_STATE {
typedef struct event {
uint64_t id;
EI1_DENM_t *denm;
void *denm;
uint32_t station_id;
uint32_t sn;
uint64_t detection_time;
@ -67,7 +68,7 @@ typedef struct cc_ssp_bm {
* @param ssp permissions
* @return 0 if event OK, 1 if event NOK
*/
enum EVENT_CHECK_R event_manage(EI1_DENM_t* denm, uint64_t* id, uint8_t* ssp, uint32_t ssp_len);
enum EVENT_CHECK_R event_manage(void* denm, uint64_t* id, uint8_t* ssp, uint32_t ssp_len);
int den_init();
void* den_service();

View File

@ -72,6 +72,14 @@ static int pver2mver(uint8_t pver) {
}
}
static int handled_mver(uint8_t* msg_data) {
if (!facilities.mver.handle_all &&
facilities.mver.defaultv != msg_data[0]) {
return 0;
}
return 1;
}
int facilities_request_result_accepted(void *responder) {
int rv = 0;
@ -685,6 +693,16 @@ static int networking_packet_indication_btp(EIS_NetworkingPacketIndication_t* np
uint64_t id = 0;
uint8_t pver = npi->data.buf[0];
// No message
if (npi->data.size == 0) {
return 1;
}
// Is message version handled
if (!handled_mver(npi->data.buf)) {
return 1;
}
// Parse message
switch (bpi->destinationPort) {
case EIS_Port_cam:
@ -700,9 +718,15 @@ static int networking_packet_indication_btp(EIS_NetworkingPacketIndication_t* np
break;
case EIS_Port_denm:
its_msg_descriptor = &asn_DEF_EI1_DENM;
its_msg = calloc(1, sizeof(EI1_DENM_t));
its_msg_type = EI1_messageID_denm;
switch (pver) {
/* Only DENMv2 is supported (as in 1.3.1 - 2.1.1) */
/* Use by default CDDv2 */
case 2:
its_msg_descriptor = &asn_DEF_EI2_DENM;
its_msg = calloc(1, sizeof(EI2_DENM_t));
its_msg_type = EI2_MessageId_denm;
break;
}
break;
case EIS_Port_ivim: