diff --git a/src/saem.c b/src/saem.c index b548313..75cb386 100644 --- a/src/saem.c +++ b/src/saem.c @@ -32,6 +32,10 @@ SAEM_CODE_R saem_check(void* fc, bulletin_t* bulletin, SAEM_t* saem, uint8_t* ne return SAEM_INVALID_HEADER_VERSION; } + if (bulletin->to_consume_len >= MAX_ANNOUNCEMENTS_LEN - 1) { + return SAEM_MAX_ANNOUNCEMENTS_REACHED; + } + pthread_mutex_lock(&bulletin->lock); if (saem->sam.body.serviceInfos) { @@ -40,86 +44,71 @@ SAEM_CODE_R saem_check(void* fc, bulletin_t* bulletin, SAEM_t* saem, uint8_t* ne uint16_t its_aid = si->serviceID; - int index = -1; + bool new_announcement = false; - for (int a = 0; a < bulletin->to_consume_len; ++a) { - // TODO allow different services for same itsAid and stationID + if (si->chOptions.extensions) { - /* Check existence through stationID and itsAid */ - if (saem->header.stationID == bulletin->to_consume[a]->station_id && - its_aid == bulletin->to_consume[a]->its_aid) { - index = a; - break; - } - } + for (int e = 0; e < si->chOptions.extensions->list.count; ++e) { + switch (si->chOptions.extensions->list.array[e]->present) { + 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 = malloc(si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size); + 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.size + ); + break; - if (index == -1) { - rv = SAEM_NEW; - if (bulletin->to_consume_len + 1 < MAX_ANNOUNCEMENTS_LEN) { - 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]->timestamp = it2s_tender_get_clock(&facilities->epv); + case ServiceInfoExt_PR_applicationDataSAM: + bulletin->to_consume[bulletin->to_consume_len]->info.data_len = 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, + si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf, + si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size + ); - if (si->chOptions.extensions) { - for (int e = 0; e < si->chOptions.extensions->list.count; ++e) { - switch (si->chOptions.extensions->list.array[e]->present) { - case ServiceInfoExt_PR_providerServiceContext: - bulletin->to_consume[bulletin->to_provide_len]->info.context_len = si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size; - bulletin->to_consume[bulletin->to_provide_len]->info.context = malloc(si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size); - memcpy(bulletin->to_consume[bulletin->to_provide_len]->info.context, - si->chOptions.extensions->list.array[e]->choice.providerServiceContext.buf, - si->chOptions.extensions->list.array[e]->choice.providerServiceContext.size - ); - break; + if (facilities->station_type != 15 && facilities->tolling.infos.length < TOLLING_INFOS_MAX_LENGTH) { + TollingPaymentInfo_t* tpi = NULL; + asn_dec_rval_t dec = uper_decode_complete( + NULL, + &asn_DEF_TollingPaymentInfo, + (void**) &tpi, + si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf, + si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size + ); + if (!dec.code) { - case ServiceInfoExt_PR_applicationDataSAM: - bulletin->to_consume[bulletin->to_provide_len]->info.data_len = si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size; - bulletin->to_consume[bulletin->to_provide_len]->info.data = malloc(si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size); - memcpy(bulletin->to_consume[bulletin->to_provide_len]->info.data, - si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf, - si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size - ); - - if (facilities->station_type != 15 && facilities->tolling.infos.length < TOLLING_INFOS_MAX_LENGTH) { - TollingPaymentInfo_t* tpi = NULL; - asn_dec_rval_t dec = uper_decode_complete( - NULL, - &asn_DEF_TollingPaymentInfo, - (void**) &tpi, - si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.buf, - si->chOptions.extensions->list.array[e]->choice.applicationDataSAM.size - ); - if (!dec.code) { - facilities->tolling.infos.z[facilities->tolling.infos.length] = tolling_info_new(&facilities->epv, tpi); - bulletin->to_consume[bulletin->to_provide_len]->info.internal_p = facilities->tolling.infos.z[facilities->tolling.infos.length]; - ++facilities->tolling.infos.length; - } else { - ASN_STRUCT_FREE(asn_DEF_TollingPaymentInfo, tpi); + bool found = false; + for (int t = 0; t < bulletin->to_consume_len; ++t) { + if (((tolling_info_s*)bulletin->to_consume[t]->info.internal_p)->asn->id == tpi->id) { + found = true; + break; } } - break; - case ServiceInfoExt_PR_addressIPv6: - memcpy(bulletin->to_consume[bulletin->to_consume_len]->endpoint.ipv6_addr, si->chOptions.extensions->list.array[e]->choice.addressIPv6.buf, 16); - break; - - case ServiceInfoExt_PR_servicePort: - bulletin->to_consume[bulletin->to_consume_len]->endpoint.port = si->chOptions.extensions->list.array[e]->choice.servicePort; - break; - - default: - break; + if (!found) { + facilities->tolling.infos.z[facilities->tolling.infos.length] = tolling_info_new(&facilities->epv, tpi); + bulletin->to_consume[bulletin->to_consume_len]->info.internal_p = facilities->tolling.infos.z[facilities->tolling.infos.length]; + ++facilities->tolling.infos.length; + new_announcement = true; + } + } else { + ASN_STRUCT_FREE(asn_DEF_TollingPaymentInfo, tpi); + } } - } - } + break; - if (neighbour) { - bulletin->to_consume[bulletin->to_consume_len]->certificate_id = malloc(8); - memcpy(bulletin->to_consume[bulletin->to_consume_len]->certificate_id, neighbour, 8); - } + case ServiceInfoExt_PR_addressIPv6: + memcpy(bulletin->to_consume[bulletin->to_consume_len]->endpoint.ipv6_addr, si->chOptions.extensions->list.array[e]->choice.addressIPv6.buf, 16); + break; - index = bulletin->to_consume_len; - ++bulletin->to_consume_len; + case ServiceInfoExt_PR_servicePort: + bulletin->to_consume[bulletin->to_consume_len]->endpoint.port = si->chOptions.extensions->list.array[e]->choice.servicePort; + break; + + default: + break; + } } } @@ -131,6 +120,18 @@ SAEM_CODE_R saem_check(void* fc, bulletin_t* bulletin, SAEM_t* saem, uint8_t* ne } } + 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]->station_id = saem->header.stationID; + bulletin->to_consume[bulletin->to_consume_len]->timestamp = it2s_tender_get_clock(&facilities->epv); + if (neighbour) { + bulletin->to_consume[bulletin->to_consume_len]->certificate_id = malloc(8); + memcpy(bulletin->to_consume[bulletin->to_consume_len]->certificate_id, neighbour, 8); + } + ++bulletin->to_consume_len; + rv = SAEM_NEW; + } + } } @@ -173,14 +174,14 @@ int mk_saem(facilities_t* facilities, uint8_t* b_saem, uint32_t* b_saem_len) { saem->sam.version = 0; saem->sam.body.serviceInfos = calloc(1, sizeof(ServiceInfos_t)); - saem->sam.body.serviceInfos->list.count = facilities->bulletin.to_provide_len; - saem->sam.body.serviceInfos->list.size = facilities->bulletin.to_provide_len * sizeof(void*); - saem->sam.body.serviceInfos->list.array = malloc(facilities->bulletin.to_provide_len * sizeof(void*)); + saem->sam.body.serviceInfos->list.count = facilities->tolling.infos.length; + saem->sam.body.serviceInfos->list.size = facilities->tolling.infos.length * sizeof(void*); + saem->sam.body.serviceInfos->list.array = malloc(facilities->tolling.infos.length * sizeof(void*)); uint8_t buf[1024]; - for (int i = 0; i < facilities->bulletin.to_provide_len; ++i) { + for (int 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]->serviceID = facilities->bulletin.to_provide[i]->its_aid; + saem->sam.body.serviceInfos->list.array[i]->serviceID = 0; saem->sam.body.serviceInfos->list.array[i]->chOptions.extensions = calloc(1, sizeof(ServiceInfoExts_t)); @@ -208,7 +209,7 @@ int mk_saem(facilities_t* facilities, uint8_t* b_saem, uint32_t* b_saem_len) { exts->list.array[2]->present = ServiceInfoExt_PR_applicationDataSAM; exts->list.array[2]->choice.applicationDataSAM.buf = malloc(1024); - enc = uper_encode_to_buffer(&asn_DEF_TollingPaymentInfo, NULL, facilities->tolling.infos.z[0]->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) { syslog_err("[facilities] [sa] failure to encode TollingPaymentInfo (%s)", enc.failed_type->name); rv = 1; @@ -244,7 +245,7 @@ int mk_saem(facilities_t* facilities, uint8_t* b_saem, uint32_t* b_saem_len) { exts->list.array[3]->present = ServiceInfoExt_PR_applicationDataSAM; exts->list.array[3]->choice.applicationDataSAM.buf = malloc(1024); - enc = uper_encode_to_buffer(&asn_DEF_TollingPaymentInfo, NULL, facilities->tolling.infos.z[0]->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) { syslog_err("[facilities] [sa] failure to encode TollingPaymentInfo (%s)", enc.failed_type->name); rv = 1; @@ -380,7 +381,6 @@ void *sa_service(void *fc) { now > bulletin->to_consume[a]->t_trigger + TOLLING_PAYMENT_MIN_PERIOD_MS && facilities->station_type != 15) { - tolling_info_s* info = (tolling_info_s*) bulletin->to_consume[a]->info.internal_p; if (!tpm_is_inside_zone(facilities, info)) { diff --git a/src/saem.h b/src/saem.h index 28fe300..64fdd6e 100644 --- a/src/saem.h +++ b/src/saem.h @@ -46,7 +46,8 @@ typedef enum SAEM_CODE { SAEM_OK, SAEM_NEW, SAEM_INVALID_HEADER_MESSAGE_ID, - SAEM_INVALID_HEADER_VERSION + SAEM_INVALID_HEADER_VERSION, + SAEM_MAX_ANNOUNCEMENTS_REACHED } SAEM_CODE_R; /**