📄 pri_facility.c
字号:
NEXT_COMPONENT(comp, i); ton = typeofnumber_for_q931(pri, ton); res = rose_number_digits_decode(pri, call, &vdata[i], len-i, value); if (res < 0) return -1; value->ton = ton; return res + 3; } while(0); return -1;}static int rose_address_decode(struct pri *pri, q931_call *call, unsigned char *data, int len, struct addressingdataelements_presentednumberunscreened *value){ int i = 0; struct rose_component *comp = NULL; unsigned char *vdata = data; int res = 0; do { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0): /* [0] unknownPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_UNKNOWN; value->ton = PRI_TON_UNKNOWN; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): /* [0] unknownPartyNumber */ res = asn1_copy_string(value->partyaddress, sizeof(value->partyaddress), comp); if (res < 0) return -1; value->npi = PRI_NPI_UNKNOWN; value->ton = PRI_TON_UNKNOWN; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): /* [1] publicPartyNumber */ res = rose_public_party_number_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_E163_E164; break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): /* [2] nsapEncodedNumber */ pri_message(pri, "!! NsapEncodedNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] dataPartyNumber */ if(rose_number_digits_decode(pri, call, comp->data, comp->len, value)) return -1; value->npi = PRI_NPI_X121 /* ??? */; value->ton = PRI_TON_UNKNOWN /* ??? */; pri_message(pri, "!! dataPartyNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): /* [4] telexPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_F69 /* ??? */; value->ton = PRI_TON_UNKNOWN /* ??? */; pri_message(pri, "!! telexPartyNumber isn't handled\n"); return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_5): /* [5] priavePartyNumber */ pri_message(pri, "!! privatePartyNumber isn't handled\n"); value->npi = PRI_NPI_PRIVATE; return -1; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_8): /* [8] nationalStandardPartyNumber */ res = rose_number_digits_decode(pri, call, comp->data, comp->len, value); if (res < 0) return -1; value->npi = PRI_NPI_NATIONAL; value->ton = PRI_TON_NATIONAL; break; default: pri_message(pri, "!! Unknown Party number component received 0x%X\n", comp->type); return -1; } ASN1_FIXUP_LEN(comp, res); NEXT_COMPONENT(comp, i); if(i < len) pri_message(pri, "!! not all information is handled from Address component\n"); return res + 2; } while (0); return -1;}static int rose_presented_number_unscreened_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; /* Fill in default values */ value->ton = PRI_TON_UNKNOWN; value->npi = PRI_NPI_E163_E164; 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] presentationAllowedNumber */ value->pres = PRES_ALLOWED_USER_NUMBER_NOT_SCREENED; size = rose_address_decode(pri, call, comp->data, comp->len, value); ASN1_FIXUP_LEN(comp, size); return size + 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1): /* [1] IMPLICIT presentationRestricted */ 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_NOT_SCREENED; return 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2): /* [2] IMPLICIT numberNotAvailableDueToInterworking */ 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; return 2; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): /* [3] presentationRestrictedNumber */ value->pres = PRES_PROHIB_USER_NUMBER_NOT_SCREENED; size = rose_address_decode(pri, call, comp->data, comp->len, value) + 2; ASN1_FIXUP_LEN(comp, size); return size + 2; default: pri_message(pri, "Invalid PresentedNumberUnscreened component 0x%X\n", comp->type); } return -1; } while (0); return -1;}static int rose_diverting_leg_information2_decode(struct pri *pri, q931_call *call, struct rose_component *sequence, int len){ int i = 0; int diversion_counter; int diversion_reason; char origcalledname[50] = "", redirectingname[50] = ""; struct addressingdataelements_presentednumberunscreened divertingnr; struct addressingdataelements_presentednumberunscreened originalcallednr; struct rose_component *comp = NULL; unsigned char *vdata = sequence->data; int res = 0; /* Data checks */ if (sequence->type != (ASN1_CONSTRUCTOR | ASN1_SEQUENCE)) { /* Constructed Sequence */ pri_message(pri, "Invalid DivertingLegInformation2Type argument\n"); return -1; } if (sequence->len == ASN1_LEN_INDEF) { len -= 4; /* For the 2 extra characters at the end * and two characters of header */ } else len -= 2; do { /* diversionCounter stuff */ GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_INTEGER, "Don't know what to do it diversionCounter is of type 0x%x\n"); ASN1_GET_INTEGER(comp, diversion_counter); NEXT_COMPONENT(comp, i); /* diversionReason stuff */ GET_COMPONENT(comp, i, vdata, len); CHECK_COMPONENT(comp, ASN1_ENUMERATED, "Invalid diversionReason type 0x%X of ROSE divertingLegInformation2 component received\n"); ASN1_GET_INTEGER(comp, diversion_reason); NEXT_COMPONENT(comp, i); diversion_reason = redirectingreason_for_q931(pri, diversion_reason); if(pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Redirection reason: %d, total diversions: %d\n", diversion_reason, diversion_counter); pri_message(NULL, "Length of message is %d\n", len); for(; i < len; NEXT_COMPONENT(comp, i)) { GET_COMPONENT(comp, i, vdata, len); switch(comp->type) { case (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0): call->origredirectingreason = redirectingreason_for_q931(pri, comp->data[0]); if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received reason for original redirection %d\n", call->origredirectingreason); break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1): res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &divertingnr); /* TODO: Fix indefinite length form hacks */ ASN1_FIXUP_LEN(comp, res); comp->len = res; if (res < 0) return -1; if (pri->debug & PRI_DEBUG_APDU) { pri_message(pri, " Received divertingNr '%s'\n", divertingnr.partyaddress); pri_message(pri, " ton = %d, pres = %d, npi = %d\n", divertingnr.ton, divertingnr.pres, divertingnr.npi); } break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2): res = rose_presented_number_unscreened_decode(pri, call, comp->data, comp->len, &originalcallednr); if (res < 0) return -1; ASN1_FIXUP_LEN(comp, res); comp->len = res; if (pri->debug & PRI_DEBUG_APDU) { pri_message(pri, " Received originalcallednr '%s'\n", originalcallednr.partyaddress); pri_message(pri, " ton = %d, pres = %d, npi = %d\n", originalcallednr.ton, originalcallednr.pres, originalcallednr.npi); } break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_3): res = asn1_name_decode(comp->data, comp->len, redirectingname, sizeof(redirectingname)); if (res < 0) return -1; ASN1_FIXUP_LEN(comp, res); comp->len = res; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received RedirectingName '%s'\n", redirectingname); break; case (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4): res = asn1_name_decode(comp->data, comp->len, origcalledname, sizeof(origcalledname)); if (res < 0) return -1; ASN1_FIXUP_LEN(comp, res); comp->len = res; if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, " Received Originally Called Name '%s'\n", origcalledname); break; default: if (comp->type == 0 && comp->len == 0) { break; /* Found termination characters */ } pri_message(pri, "!! Invalid DivertingLegInformation2 component received 0x%X\n", comp->type); return -1; } } if (divertingnr.pres >= 0) { call->redirectingplan = divertingnr.npi; call->redirectingpres = divertingnr.pres; call->redirectingreason = diversion_reason; libpri_copy_string(call->redirectingnum, divertingnr.partyaddress, sizeof(call->redirectingnum)); } if (originalcallednr.pres >= 0) { call->origcalledplan = originalcallednr.npi; call->origcalledpres = originalcallednr.pres; libpri_copy_string(call->origcallednum, originalcallednr.partyaddress, sizeof(call->origcallednum)); } libpri_copy_string(call->redirectingname, redirectingname, sizeof(call->redirectingname)); libpri_copy_string(call->origcalledname, origcalledname, sizeof(call->origcalledname)); return 0; } while (0); return -1;} static int rose_diverting_leg_information2_encode(struct pri *pri, q931_call *call){ int i = 0, j, compsp = 0; struct rose_component *comp, *compstk[10]; unsigned char buffer[256]; int len = 253; #if 0 /* This is not required by specifications */ if (!strlen(call->callername)) { return -1; }#endif buffer[i] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS); i++; /* Interpretation component */ ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer, i, 0x00 /* Discard unrecognized invokes */); ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Invoke component contents */ /* Invoke ID */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, get_invokeid(pri)); /* Operation Tag */ /* ROSE operationId component */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, ROSE_DIVERTING_LEG_INFORMATION2); /* ROSE ARGUMENT component */ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* ROSE DivertingLegInformation2.diversionCounter component */ /* Always is 1 because other isn't available in the current design */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1); /* ROSE DivertingLegInformation2.diversionReason component */ ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, redirectingreason_from_q931(pri, call->redirectingreason)); /* ROSE DivertingLegInformation2.divertingNr component */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Redirecting information always not screened */ switch(call->redirectingpres) { case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: if (call->redirectingnum && strlen(call->redirectingnum)) { ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* NPI of redirected number is not supported in the current design */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4)); j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum)); if (j < 0) return -1; i += j; ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); break; } /* fall through */ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: case PRES_PROHIB_USER_NUMBER_NOT_SCREENED: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); break; /* Don't know how to handle this */ case PRES_ALLOWED_NETWORK_NUMBER: case PRES_PROHIB_NETWORK_NUMBER: case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); break; default: pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres); case PRES_NUMBER_NOT_AVAILABLE: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i); break; } ASN1_FIXUP(compstk, compsp, buffer, i); /* ROSE DivertingLegInformation2.originalCalledNr component */ /* This information isn't supported by current design - duplicate divertingNr */ ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_2), buffer, i); ASN1_PUSH(compstk, compsp, comp); /* Redirecting information always not screened */ switch(call->redirectingpres) { case PRES_ALLOWED_USER_NUMBER_NOT_SCREENED: case PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN: if (call->redirectingnum && strlen(call->redirectingnum)) { ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, typeofnumber_from_q931(pri, call->redirectingplan >> 4)); j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, call->redirectingnum, strlen(call->redirectingnum)); if (j < 0) return -1; i += j; ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); break; } /* fall through */ case PRES_PROHIB_USER_NUMBER_PASSED_SCREEN: case PRES_PROHIB_USER_NUMBER_NOT_SCREENED: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); break; /* Don't know how to handle this */ case PRES_ALLOWED_NETWORK_NUMBER: case PRES_PROHIB_NETWORK_NUMBER: case PRES_ALLOWED_USER_NUMBER_FAILED_SCREEN: case PRES_PROHIB_USER_NUMBER_FAILED_SCREEN: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i); break; default: pri_message(pri, "!! Undefined presentation value for redirecting number: %d\n", call->redirectingpres); case PRES_NUMBER_NOT_AVAILABLE: ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i); break; } ASN1_FIXUP(compstk, compsp, buffer, i); /* Fix length of stacked components */ while(compsp > 0) { ASN1_FIXUP(compstk, compsp, buffer, i); } if (pri_call_apdu_queue(call, Q931_SETUP, buffer, i, NULL, NULL)) return -1; return 0;}/* Send the rltThirdParty: Invoke */int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2){ int i = 0; unsigned char buffer[256]; struct rose_component *comp = NULL, *compstk[10]; const unsigned char rlt_3rd_pty = RLT_THIRD_PARTY; q931_call *callwithid = NULL, *apdubearer = NULL; int compsp = 0; if (c2->transferable) { apdubearer = c1; callwithid = c2; } else if (c1->transferable) { apdubearer = c2; callwithid = c1; } else return -1; buffer[i++] = (Q932_PROTOCOL_ROSE); 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_3rd_pty); /* Operation Tag */ ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, rlt_3rd_pty); /* Additional RLT invoke info - Octet 12 */ ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i); ASN1_PUSH(compstk, compsp, comp); ASN1_ADD_WORDCOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer, i, callwithid->rlt_call_id & 0xFFFFFF); /* Length is 3 octets */ /* Reason for redirect - unused, set to 129 */ ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_1), buffer, i, 0); ASN1_FIXUP(compstk, compsp, buffer, i); ASN1_FIXUP(compstk, compsp, buffer, i); if (pri_call_apdu_queue(apdubearer, Q931_FACILITY, buffer, i, NULL, NULL))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -