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-v1-evrsrm
-lit2s-asn-etsi-its-v2-cdd-2.2.1 -lit2s-asn-etsi-its-v2-cdd-2.2.1
-lit2s-asn-etsi-its-v2-cam -lit2s-asn-etsi-its-v2-cam
-lit2s-asn-etsi-its-v2-denm
-lit2s-tender -lit2s-tender
-lm -lm
-lrt -lrt

View File

@ -6,6 +6,8 @@
#include <it2s-tender/time.h> #include <it2s-tender/time.h>
#include <it2s-tender/space.h> #include <it2s-tender/space.h>
#define DENM_VERSION(denm) (((EI1_ItsPduHeader_t*)(denm))->protocolVersion)
const cc_ssp_bm_t CC_SSP_BM_MAP[] = { const cc_ssp_bm_t CC_SSP_BM_MAP[] = {
{"trafficCondition", 1, 0x80000000}, {"trafficCondition", 1, 0x80000000},
{"accident", 2, 0x40000000}, {"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; int rv = 0;
den_t* den = &facilities.den; 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; uint64_t e_detection_time, e_reference_time;
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.detectionTime, &e_detection_time); asn_INTEGER2ulong((INTEGER_t*) &denm_c->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.referenceTime, &e_reference_time);
if (e_detection_time > e_reference_time) { if (e_detection_time > e_reference_time) {
return EVENT_INVALID; return EVENT_INVALID;
} }
// Check if event cause code type is permitted by the issuing ticket // Check if event cause code type is permitted by the issuing ticket
if (ssp && denm->denm.situation) { if (ssp && denm_c->denm.situation) {
if (!permissions_check(denm->denm.situation->eventType.causeCode, ssp, ssp_len)) { if (!permissions_check(cause_code, ssp, ssp_len)) {
return EVENT_BAD_PERMISSIONS; return EVENT_BAD_PERMISSIONS;
} }
} }
uint32_t e_validity_duration; uint32_t e_validity_duration;
if (denm->denm.management.validityDuration != NULL) { if (denm_c->denm.management.validityDuration != NULL) {
e_validity_duration = *(uint32_t *) denm->denm.management.validityDuration * 1000; // validityDuration comes in seconds e_validity_duration = *(uint32_t *) denm_c->denm.management.validityDuration * 1000; // validityDuration comes in seconds
} else { } else {
e_validity_duration = 600 * 1000; 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) { for (int i = 0; i < den->n_max_events; ++i) {
if (den->events[i]->enabled) { if (den->events[i]->enabled) {
if (den->events[i]->station_id == denm->denm.management.actionID.originatingStationID && if (den->events[i]->station_id == action_id_origin_station &&
den->events[i]->sn == denm->denm.management.actionID.sequenceNumber) { den->events[i]->sn == action_id_seq_num) {
is_new = false; 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 (is_update) {
if (denm->denm.management.termination != NULL) { if (denm_c->denm.management.termination != NULL) {
if (*denm->denm.management.termination == 0) { if (*denm_c->denm.management.termination == 0) {
return EVENT_CANCELLATION; return EVENT_CANCELLATION;
} else if (*denm->denm.management.termination == 1) { } else if (*denm_c->denm.management.termination == 1) {
return EVENT_NEGATION; 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; 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; den_t* den = &facilities.den;
uint64_t now = itss_time_get(); 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; uint64_t e_detection_time, e_reference_time;
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.detectionTime, &e_detection_time); asn_INTEGER2ulong((INTEGER_t*) &denm_c->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.referenceTime, &e_reference_time);
uint32_t e_validity_duration; uint32_t e_validity_duration;
if (denm->denm.management.validityDuration != NULL) { if (denm_c->denm.management.validityDuration != NULL) {
e_validity_duration = *(uint32_t *) denm->denm.management.validityDuration * 1000; // validityDuration comes in seconds e_validity_duration = *(uint32_t *) denm_c->denm.management.validityDuration * 1000; // validityDuration comes in seconds
} else { } else {
e_validity_duration = 600 * 1000; 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; uint8_t state = EVENT_ACTIVE;
if (denm->denm.management.termination != NULL) { if (denm_c->denm.management.termination != NULL) {
if (*(denm->denm.management.termination) == 0) { if (*(denm_c->denm.management.termination) == 0) {
state = EVENT_CANCELLED; state = EVENT_CANCELLED;
} else if (*(denm->denm.management.termination) == 1) { } else if (*(denm_c->denm.management.termination) == 1) {
state = EVENT_NEGATED; 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]->id = *id;
den->events[index]->enabled = true; den->events[index]->enabled = true;
den->events[index]->state = state; den->events[index]->state = state;
den->events[index]->station_id = denm->denm.management.actionID.originatingStationID; den->events[index]->station_id = action_id_origin_station;
den->events[index]->sn = denm->denm.management.actionID.sequenceNumber; den->events[index]->sn = action_id_seq_num;
den->events[index]->detection_time = e_detection_time; den->events[index]->detection_time = e_detection_time;
den->events[index]->reference_time = e_reference_time; den->events[index]->reference_time = e_reference_time;
den->events[index]->expiration_time = e_detection_time + e_validity_duration; den->events[index]->expiration_time = e_detection_time + e_validity_duration;
den->events[index]->latitude = denm->denm.management.eventPosition.latitude; den->events[index]->latitude = denm_c->denm.management.eventPosition.latitude;
den->events[index]->longitude = denm->denm.management.eventPosition.longitude; den->events[index]->longitude = denm_c->denm.management.eventPosition.longitude;
den->events[index]->denm = denm; den->events[index]->denm = denm;
if (denm->denm.management.actionID.sequenceNumber > den->sn) { if (action_id_seq_num > den->sn) {
den->sn = denm->denm.management.actionID.sequenceNumber; 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 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; den_t* den = &facilities.den;
uint64_t now = itss_time_get(); 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; uint64_t e_detection_time, e_reference_time;
asn_INTEGER2ulong((INTEGER_t*) &denm->denm.management.detectionTime, &e_detection_time); asn_INTEGER2ulong((INTEGER_t*) &denm_c->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.referenceTime, &e_reference_time);
uint8_t state = EVENT_ACTIVE; uint8_t state = EVENT_ACTIVE;
if (denm->denm.management.termination != NULL) { if (denm_c->denm.management.termination != NULL) {
if (*(denm->denm.management.termination) == 0) { if (*(denm_c->denm.management.termination) == 0) {
state = EVENT_CANCELLED; state = EVENT_CANCELLED;
} else if (*(denm->denm.management.termination) == 1) { } else if (*(denm_c->denm.management.termination) == 1) {
state = EVENT_NEGATED; 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) { for (int i = 0; i < den->n_max_events; ++i) {
if (den->events[i]->enabled) { if (den->events[i]->enabled) {
if (den->events[i]->station_id == denm->denm.management.actionID.originatingStationID && if (den->events[i]->station_id == action_id_origin_station &&
den->events[i]->sn == denm->denm.management.actionID.sequenceNumber) { den->events[i]->sn == action_id_seq_num) {
index = i; index = i;
break; 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]->detection_time = e_detection_time;
den->events[index]->reference_time = e_reference_time; den->events[index]->reference_time = e_reference_time;
if (denm->denm.management.validityDuration != NULL) { if (denm_c->denm.management.validityDuration != NULL) {
den->events[index]->expiration_time = e_detection_time + *(uint32_t *) denm->denm.management.validityDuration * 1000; 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 if (state == EVENT_CANCELLED || state == EVENT_NEGATED) { // Keep terminated events for 10 mins
den->events[index]->expiration_time = now + 600 * 1000; den->events[index]->expiration_time = now + 600 * 1000;
} }
den->events[index]->latitude = denm->denm.management.eventPosition.latitude; den->events[index]->latitude = denm_c->denm.management.eventPosition.latitude;
den->events[index]->longitude = denm->denm.management.eventPosition.longitude; den->events[index]->longitude = denm_c->denm.management.eventPosition.longitude;
ASN_STRUCT_FREE(asn_DEF_EI1_DENM, den->events[index]->denm); ASN_STRUCT_FREE(asn_DEF_EI1_DENM, den->events[index]->denm);
den->events[index]->denm = 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 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; int rv = 0;
switch (rv = event_check(denm, ssp, ssp_len)) { switch (rv = event_check(denm, ssp, ssp_len)) {
case EVENT_NEW: case EVENT_NEW:

View File

@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include <it2s-asn/etsi-its-v1/denm/EI1_DENM.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 <pthread.h>
#include <stdbool.h> #include <stdbool.h>
@ -16,7 +17,7 @@ enum EVENT_STATE {
typedef struct event { typedef struct event {
uint64_t id; uint64_t id;
EI1_DENM_t *denm; void *denm;
uint32_t station_id; uint32_t station_id;
uint32_t sn; uint32_t sn;
uint64_t detection_time; uint64_t detection_time;
@ -67,7 +68,7 @@ typedef struct cc_ssp_bm {
* @param ssp permissions * @param ssp permissions
* @return 0 if event OK, 1 if event NOK * @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(); int den_init();
void* den_service(); 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 facilities_request_result_accepted(void *responder) {
int rv = 0; int rv = 0;
@ -685,6 +693,16 @@ static int networking_packet_indication_btp(EIS_NetworkingPacketIndication_t* np
uint64_t id = 0; uint64_t id = 0;
uint8_t pver = npi->data.buf[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 // Parse message
switch (bpi->destinationPort) { switch (bpi->destinationPort) {
case EIS_Port_cam: case EIS_Port_cam:
@ -700,9 +718,15 @@ static int networking_packet_indication_btp(EIS_NetworkingPacketIndication_t* np
break; break;
case EIS_Port_denm: case EIS_Port_denm:
its_msg_descriptor = &asn_DEF_EI1_DENM; switch (pver) {
its_msg = calloc(1, sizeof(EI1_DENM_t)); /* Only DENMv2 is supported (as in 1.3.1 - 2.1.1) */
its_msg_type = EI1_messageID_denm; /* 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; break;
case EIS_Port_ivim: case EIS_Port_ivim: