📄 pri_facility.c
字号:
long chargingunits = 0, chargetype = -1, temp, chargeIdentifier = -1; unsigned char *vdata = data; struct rose_component *comp1 = NULL, *comp2 = NULL, *comp3 = NULL; int pos1 = 0, pos2, pos3, sublen2, sublen3; struct addressingdataelements_presentednumberunscreened chargednr; if (pri->debug & PRI_DEBUG_AOC) dump_apdu (pri, data, len); do { GET_COMPONENT(comp1, pos1, vdata, len); /* AOCEChargingUnitInfo */ CHECK_COMPONENT(comp1, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but Received 0x%02X\n"); SUB_COMPONENT(comp1, pos1); GET_COMPONENT(comp1, pos1, vdata, len); switch (comp1->type) { case (ASN1_SEQUENCE | ASN1_CONSTRUCTOR): /* specificChargingUnits */ sublen2 = comp1->len; pos2 = pos1; comp2 = comp1; SUB_COMPONENT(comp2, pos2); do { GET_COMPONENT(comp2, pos2, vdata, len); switch (comp2->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* RecordedUnitsList (0xA1) */ SUB_COMPONENT(comp2, pos2); GET_COMPONENT(comp2, pos2, vdata, len); CHECK_COMPONENT(comp2, ASN1_SEQUENCE, "!! Invalid AOC-E Charging Unit argument. Expected Sequence (0x30) but received 0x02%X\n"); /* RecordedUnits */ sublen3 = pos2 + comp2->len; pos3 = pos2; comp3 = comp2; SUB_COMPONENT(comp3, pos3); do { GET_COMPONENT(comp3, pos3, vdata, len); switch (comp3->type) { case ASN1_INTEGER: /* numberOfUnits */ ASN1_GET_INTEGER(comp3, temp); chargingunits += temp; case ASN1_NULL: /* notAvailable */ break; default: pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnits\n", comp3->type); } NEXT_COMPONENT(comp3, pos3); } while (pos3 < sublen3); if (pri->debug & PRI_DEBUG_AOC) pri_message(pri, "Channel %d/%d, Call %d - received AOC-E charging: %i unit%s\n", call->ds1no, call->channelno, call->cr, chargingunits, (chargingunits == 1) ? "" : "s"); break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* AOCEBillingID (0xA2) */ SUB_COMPONENT(comp2, pos2); GET_COMPONENT(comp2, pos2, vdata, len); ASN1_GET_INTEGER(comp2, chargetype); pri_message(pri, "!! not handled: Channel %d/%d, Call %d - received AOC-E billing ID: %i\n", call->ds1no, call->channelno, call->cr, chargetype); break; default: pri_message(pri, "!! Don't know how to handle 0x%02X in AOC-E RecordedUnitsList\n", comp2->type); } NEXT_COMPONENT(comp2, pos2); } while (pos2 < sublen2); break; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* freeOfCharge (0x81) */ if (pri->debug & PRI_DEBUG_AOC) pri_message(pri, "Channel %d/%d, Call %d - received AOC-E free of charge\n", call->ds1no, call->channelno, call->cr); chargingunits = 0; break; default: pri_message(pri, "!! Invalid AOC-E specificChargingUnits. Expected Sequence (0x30) or Object Identifier (0x81/0x01) but received 0x%02X\n", comp1->type); } NEXT_COMPONENT(comp1, pos1); GET_COMPONENT(comp1, pos1, vdata, len); /* get optional chargingAssociation. will 'break' when reached end of structure */ switch (comp1->type) { /* TODO: charged number is untested - please report! */ case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* chargedNumber (0xA0) */ if(rose_presented_number_unscreened_decode(pri, call, comp1->data, comp1->len, &chargednr) != 0) return -1; pri_message(pri, "!! not handled: Received ChargedNr '%s' \n", chargednr.partyaddress); pri_message(pri, " ton = %d, pres = %d, npi = %d\n", chargednr.ton, chargednr.pres, chargednr.npi); break; case ASN1_INTEGER: ASN1_GET_INTEGER(comp1, chargeIdentifier); break; default: pri_message(pri, "!! Invalid AOC-E chargingAssociation. Expected Object Identifier (0xA0) or Integer (0x02) but received 0x%02X\n", comp1->type); } NEXT_COMPONENT(comp1, pos1); } while (pos1 < len); if (pos1 < len) { pri_message(pri, "!! Only reached position %i in %i bytes long AOC-E structure:", pos1, len ); dump_apdu (pri, data, len); return -1; /* oops - aborted before */ } call->aoc_units = chargingunits; return 0;}static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long chargedunits){ /* sample data: [ 91 a1 12 02 02 3a 78 02 01 24 30 09 30 07 a1 05 30 03 02 01 01 ] */ int i = 0, res = 0, compsp = 0; unsigned char buffer[255] = ""; struct rose_component *comp = NULL, *compstk[10]; /* ROSE protocol (0x91)*/ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_ROSE); /* ROSE Component (0xA1,len)*/ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); /* ROSE invokeId component (0x02,len,id)*/ ASN1_ADD_WORDCOMP(comp, INVOKE_IDENTIFIER, buffer, i, ++pri->last_invoke); /* ROSE operationId component (0x02,0x01,0x24)*/ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_AOC_AOCE_CHARGING_UNIT); /* AOCEChargingUnitInfo (0x30,len) */ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); if (chargedunits > 0) { /* SpecificChargingUnits (0x30,len) */ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* RecordedUnitsList (0xA1,len) */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* RecordedUnits (0x30,len) */ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* NumberOfUnits (0x02,len,charge) */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, chargedunits); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); } else { /* freeOfCharge (0x81,0) */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); } ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); if (pri->debug & PRI_DEBUG_AOC) dump_apdu (pri, buffer, i); /* code below is untested */ res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL); if (res) { pri_message(pri, "Could not queue APDU in facility message\n"); return -1; } /* Remember that if we queue a facility IE for a facility message we * have to explicitly send the facility message ourselves */ res = q931_facility(c->pri, c); if (res) { pri_message(pri, "Could not schedule facility message for call %d\n", c->cr); return -1; } return 0;}/* End AOC */static int rose_calling_name_decode(struct pri *pri, q931_call *call, struct rose_component *choice, int len){ int i = 0; struct rose_component *comp = NULL; unsigned char *vdata = choice->data; int characterSet = 1; switch (choice->type) { case ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE: memcpy(call->callername, choice->data, choice->len); call->callername[choice->len] = 0; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received simple calling name '%s'\n", call->callername); return 0; case ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED: do { GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_OCTETSTRING, "Don't know what to do if nameData is of type 0x%x\n"); memcpy(call->callername, comp->data, comp->len); call->callername[comp->len] = 0; NEXT_COMPONENT(comp, i); GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do if CharacterSet is of type 0x%x\n"); ASN1_GET_INTEGER(comp, characterSet); } while (0); if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received extended calling name '%s', characterset %d\n", call->callername, characterSet); return 0; case ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE: case ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED: case ROSE_NAME_PRESENTATION_RESTRICTED_NULL: case ROSE_NAME_NOT_AVAIL: default: if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Do not handle argument of type 0x%X\n", choice->type); return -1; }}/* ===== Call Transfer Supplementary Service (ECMA-178) ===== */static int rose_party_number_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value){ int i = 0; int size = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; do { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT NumberDigits -- default: unknownPartyNumber */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PartyNumber: UnknownPartyNumber len=%d\n", len); size = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; value->npi = PRI_NPI_UNKNOWN; value->ton = PRI_TON_UNKNOWN; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] IMPLICIT PublicPartyNumber */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PartyNumber: PublicPartyNumber len=%d\n", len); size = rose_public_party_number_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; value->npi = PRI_NPI_E163_E164; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT NumberDigits -- not used: dataPartyNumber */ pri_message(pri, "!! PartyNumber: dataPartyNumber is reserved!\n"); size = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; value->npi = PRI_NPI_X121 /* ??? */; value->ton = PRI_TON_UNKNOWN /* ??? */; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] IMPLICIT NumberDigits -- not used: telexPartyNumber */ pri_message(pri, "!! PartyNumber: telexPartyNumber is reserved!\n"); size = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; value->npi = PRI_NPI_F69 /* ??? */; value->ton = PRI_TON_UNKNOWN /* ??? */; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] IMPLICIT PrivatePartyNumber */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PartyNumber: PrivatePartyNumber len=%d\n", len); size = rose_private_party_number_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; value->npi = PRI_NPI_PRIVATE; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] IMPLICIT NumberDigits -- not used: nationalStandatdPartyNumber */ pri_message(pri, "!! PartyNumber: nationalStandardPartyNumber is reserved!\n"); size = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; value->npi = PRI_NPI_NATIONAL; value->ton = PRI_TON_NATIONAL; break; default: pri_message(pri, "Invalid PartyNumber component 0x%X\n", comp->type); return -1; } ASN1_FIXUP_LEN(comp, size); if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PartyNumber: '%s' size=%d len=%d\n", value->partyaddress, size, len); return size; } while (0); return -1;}static int rose_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value){ int i = 0; int size = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; int scrind = -1; do { /* Party Number */ GET_COMPONENT(comp, i, vdata, len); size = rose_party_number_decode(pri, call, (u_int8_t *)comp, comp->len + 2, (struct addressingdataelements_presentednumberunscreened*) value); if (size < 0) return -1; comp->len = size; NEXT_COMPONENT(comp, i); /* Screening Indicator */ GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Don't know what to do with NumberScreened ROSE component type 0x%x\n"); ASN1_GET_INTEGER(comp, scrind); // Todo: scrind = screeningindicator_for_q931(pri, scrind); NEXT_COMPONENT(comp, i); value->scrind = scrind; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " NumberScreened: '%s' ScreeningIndicator=%d i=%d len=%d\n", value->partyaddress, scrind, i, len); return i-2; // We do not have a sequence header here. } while (0); return -1;}static int rose_presented_number_screened_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberscreened *value){ int i = 0; int size = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; /* Fill in default values */ value->ton = PRI_TON_UNKNOWN; value->npi = PRI_NPI_UNKNOWN; value->pres = -1; /* Data is not available */ do { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] IMPLICIT presentationAllowedNumber */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PresentedNumberScreened: presentationAllowedNumber comp->len=%d\n", comp->len); value->pres = PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN; size = rose_number_screened_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; ASN1_FIXUP_LEN(comp, size); return size + 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PresentedNumberScreened: presentationRestricted comp->len=%d\n", comp->len); if (comp->len != 0) { /* must be NULL */ pri_error(pri, "!! Invalid PresentationRestricted component received (len != 0)\n"); return -1; } value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; return 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PresentedNumberScreened: NumberNotAvailableDueToInterworking comp->len=%d\n", comp->len); if (comp->len != 0) { /* must be NULL */ pri_error(pri, "!! Invalid NumberNotAvailableDueToInterworking component received (len != 0)\n"); return -1; } value->pres = PRES_NUMBER_NOT_AVAILABLE; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PresentedNumberScreened: numberNotAvailableDueToInterworking Type=0x%X i=%d len=%d size=%d\n", comp->type, i, len); return 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] IMPLICIT presentationRestrictedNumber */ if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " PresentedNumberScreened: presentationRestrictedNumber comp->len=%d\n", comp->len); value->pres = PRES_PROHIB_USER_NUMBER_PASSED_SCREEN; size = rose_number_screened_decode(pri, call, comp->data, comp->len, value); if (size < 0) return -1; ASN1_FIXUP_LEN(comp, size); return size + 2; default: pri_message(pri, "Invalid PresentedNumberScreened component 0x%X\n", comp->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -