From 117ed93e31a4b35f6fb324af884d3c2bec6095a8 Mon Sep 17 00:00:00 2001 From: emanuel Date: Tue, 19 Mar 2024 11:21:54 +0000 Subject: [PATCH] denm: Handle 2.1.1 messages --- src/CMakeLists.txt | 1 + src/denm.c | 159 ++++++++++++++++++++++++++++++++++----------- src/denm.h | 5 +- src/requests.c | 30 ++++++++- 4 files changed, 151 insertions(+), 44 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ff4b4e7..c8294d8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -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 diff --git a/src/denm.c b/src/denm.c index 7be0a2e..5763ddb 100644 --- a/src/denm.c +++ b/src/denm.c @@ -6,6 +6,8 @@ #include #include +#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: diff --git a/src/denm.h b/src/denm.h index b7de1fe..30a391c 100644 --- a/src/denm.h +++ b/src/denm.h @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -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(); diff --git a/src/requests.c b/src/requests.c index a057dce..7df53c5 100644 --- a/src/requests.c +++ b/src/requests.c @@ -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: