📄 pri_facility.c
字号:
return -1; if (q931_facility(apdubearer->pri, apdubearer)) { pri_message(pri, "Could not schedule facility message for call %d\n", apdubearer->cr); return -1; } return 0;}static int add_dms100_transfer_ability_apdu(struct pri *pri, q931_call *c){ int i = 0; unsigned char buffer[256]; struct rose_component *comp = NULL, *compstk[10]; const unsigned char rlt_op_ind = RLT_OPERATION_IND; int compsp = 0; buffer[i++] = (Q932_PROTOCOL_ROSE); /* Note to self: DON'T set the EXT bit */ buffer[i++] = (0x80 | RLT_SERVICE_ID); /* Service Identifier octet */ ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Invoke ID is set to the operation ID */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind); /* Operation Tag - basically the same as the invoke ID tag */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_op_ind); ASN1_FIXUP(compstk, compsp, buffer, i); if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL)) return -1; else return 0;}/* Sending callername information functions */static int add_callername_facility_ies(struct pri *pri, q931_call *c, int cpe){ int res = 0; int i = 0; unsigned char buffer[256]; unsigned char namelen = 0; struct rose_component *comp = NULL, *compstk[10]; int compsp = 0; int mymessage = 0; static unsigned char op_tag[] = { 0x2a, /* informationFollowing 42 */ 0x86, 0x48, 0xce, 0x15, 0x00, 0x04 }; if (!strlen(c->callername)) { return -1; } buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); /* Interpretation component */ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Invoke ID */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); /* Operation Tag */ res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag)); if (res < 0) return -1; i += res; ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); ASN1_FIXUP(compstk, compsp, buffer, i); if (!cpe) { if (pri_call_apdu_queue(c, Q931_SETUP, buffer, i, NULL, NULL)) return -1; } /* Now the APDU that contains the information that needs sent. * We can reuse the buffer since the queue function doesn't * need it. */ i = 0; namelen = strlen(c->callername); if (namelen > 50) { namelen = 50; /* truncate the name */ } buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); /* Interpretation component */ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Invoke ID */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); /* Operation ID: Calling name */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, SS_CNID_CALLINGNAME); res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, 50, c->callername, namelen); if (res < 0) return -1; i += res; ASN1_FIXUP(compstk, compsp, buffer, i); if (cpe) mymessage = Q931_SETUP; else mymessage = Q931_FACILITY; if (pri_call_apdu_queue(c, mymessage, buffer, i, NULL, NULL)) return -1; return 0;}/* End Callername *//* MWI related encode and decode functions */static void mwi_activate_encode_cb(void *data){ return;}int mwi_message_send(struct pri* pri, q931_call *call, struct pri_sr *req, int activate){ int i = 0; unsigned char buffer[255] = ""; int destlen = strlen(req->called); struct rose_component *comp = NULL, *compstk[10]; int compsp = 0; int res; if (destlen <= 0) { return -1; } else if (destlen > 20) destlen = 20; /* Destination number cannot be greater then 20 digits */ buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); /* Interpretation component */ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, (activate) ? SS_MWI_ACTIVATE : SS_MWI_DEACTIVATE); ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* PartyNumber */ res = asn1_string_encode((ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), &buffer[i], sizeof(buffer)-i, destlen, req->called, destlen); if (res < 0) return -1; i += res; /* Enumeration: basicService */ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1 /* contents: Voice */); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); return pri_call_apdu_queue(call, Q931_SETUP, buffer, i, mwi_activate_encode_cb, NULL);}/* End MWI *//* EECT functions */int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2){ /* Did all the tests to see if we're on the same PRI and * are on a compatible switchtype */ /* TODO */ int i = 0; int res = 0; unsigned char buffer[255] = ""; unsigned short call_reference = c2->cr; struct rose_component *comp = NULL, *compstk[10]; int compsp = 0; static unsigned char op_tag[] = { 0x2A, 0x86, 0x48, 0xCE, 0x15, 0x00, 0x08, }; buffer[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); /* Interpretation component */ ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, 0); ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); res = asn1_string_encode(ASN1_OBJECTIDENTIFIER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag)); if (res < 0) return -1; i += res; ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer, i, call_reference); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); res = pri_call_apdu_queue(c1, 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(c1->pri, c1); if (res) { pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr); return -1; } return 0;}/* End EECT *//* AOC */static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len) { int chargingcase = -1; unsigned char *vdata = data; struct rose_component *comp = NULL; int pos1 = 0; if (pri->debug & PRI_DEBUG_AOC) dump_apdu (pri, data, len); do { GET_COMPONENT(comp, pos1, vdata, len); CHECK_COMPONENT(comp, ASN1_ENUMERATED, "!! Invalid AOC Charging Request argument. Expected Enumerated (0x0A) but Received 0x%02X\n"); ASN1_GET_INTEGER(comp, chargingcase); if (chargingcase >= 0 && chargingcase <= 2) { if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Channel %d/%d, Call %d - received AOC charging request - charging case: %i\n", call->ds1no, call->channelno, call->cr, chargingcase); } else { pri_message(pri, "!! unkown AOC ChargingCase: 0x%02X", chargingcase); chargingcase = -1; } NEXT_COMPONENT(comp, 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; /* Aborted before */ } return 0;} static int aoc_aoce_charging_unit_decode(struct pri *pri, q931_call *call, unsigned char *data, int len) { 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) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -