Merging in additional Q.SIG features in #13454. Includes Q.SIG physical/logical channel mapping support, extended coding of Q.SIG name operations (calling name), and call rerouting support via added dialplan application.
git-svn-id: https://origsvn.digium.com/svn/libpri/branches/1.4@636 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
parent
aeb5a6d284
commit
e1bfec4b1e
11
libpri.h
11
libpri.h
@ -615,6 +615,10 @@ void pri_set_error(void (*__pri_error)(struct pri *pri, char *));
|
||||
#define PRI_SET_OVERLAPDIAL
|
||||
void pri_set_overlapdial(struct pri *pri,int state);
|
||||
|
||||
/* QSIG logical channel mapping option, do not skip channel 16 */
|
||||
#define PRI_SET_CHAN_MAPPING_LOGICAL
|
||||
void pri_set_chan_mapping_logical(struct pri *pri, int state);
|
||||
|
||||
#define PRI_DUMP_INFO_STR
|
||||
char *pri_dump_info_str(struct pri *pri);
|
||||
|
||||
@ -622,9 +626,12 @@ char *pri_dump_info_str(struct pri *pri);
|
||||
int pri_fd(struct pri *pri);
|
||||
|
||||
#define PRI_PROGRESS
|
||||
/* Send call proceeding */
|
||||
/* Send progress */
|
||||
int pri_progress(struct pri *pri, q931_call *c, int channel, int info);
|
||||
|
||||
/* Send progress with cause IE */
|
||||
int pri_progress_with_cause(struct pri *pri, q931_call *c, int channel, int info, int cause);
|
||||
|
||||
#define PRI_PROCEEDING_FULL
|
||||
/* Send call proceeding */
|
||||
int pri_proceeding(struct pri *pri, q931_call *c, int channel, int info);
|
||||
@ -647,6 +654,8 @@ void pri_enslave(struct pri *master, struct pri *slave);
|
||||
/* Send notification */
|
||||
int pri_notify(struct pri *pri, q931_call *c, int channel, int info);
|
||||
|
||||
int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason);
|
||||
|
||||
/* Get/Set PRI Timers */
|
||||
#define PRI_GETSET_TIMERS
|
||||
int pri_set_timer(struct pri *pri, int timer, int value);
|
||||
|
25
pri.c
25
pri.c
@ -483,10 +483,19 @@ int pri_proceeding(struct pri *pri, q931_call *call, int channel, int info)
|
||||
return q931_call_proceeding(pri, call, channel, info);
|
||||
}
|
||||
|
||||
int pri_progress_with_cause(struct pri *pri, q931_call *call, int channel, int info, int cause)
|
||||
{
|
||||
if (!pri || !call)
|
||||
return -1;
|
||||
|
||||
return q931_call_progress_with_cause(pri, call, channel, info, cause);
|
||||
}
|
||||
|
||||
int pri_progress(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
return -1;
|
||||
|
||||
return q931_call_progress(pri, call, channel, info);
|
||||
}
|
||||
|
||||
@ -505,6 +514,15 @@ int pri_keypad_facility(struct pri *pri, q931_call *call, char *digits)
|
||||
return q931_keypad_facility(pri, call, digits);
|
||||
}
|
||||
|
||||
|
||||
int pri_callrerouting_facility(struct pri *pri, q931_call *call, const char *dest, const char* original, const char* reason)
|
||||
{
|
||||
if (!pri || !call)
|
||||
return -1;
|
||||
|
||||
return qsig_cf_callrerouting(pri, call, dest, original, reason);
|
||||
}
|
||||
|
||||
int pri_notify(struct pri *pri, q931_call *call, int channel, int info)
|
||||
{
|
||||
if (!pri || !call)
|
||||
@ -787,6 +805,12 @@ void pri_set_overlapdial(struct pri *pri,int state)
|
||||
pri->overlapdial = state;
|
||||
}
|
||||
|
||||
void pri_set_chan_mapping_logical(struct pri *pri, int state)
|
||||
{
|
||||
if (pri->switchtype == PRI_SWITCH_QSIG)
|
||||
pri->chan_mapping_logical = state;
|
||||
}
|
||||
|
||||
void pri_set_inbanddisconnect(struct pri *pri, unsigned int enable)
|
||||
{
|
||||
pri->acceptinbanddisconnect = (enable != 0);
|
||||
@ -830,6 +854,7 @@ char *pri_dump_info_str(struct pri *pri)
|
||||
len += sprintf(buf + len, "Retrans: %d\n", pri->retrans);
|
||||
len += sprintf(buf + len, "Busy: %d\n", pri->busy);
|
||||
len += sprintf(buf + len, "Overlap Dial: %d\n", pri->overlapdial);
|
||||
len += sprintf(buf + len, "Logical Channel Mapping: %d\n", pri->chan_mapping_logical);
|
||||
len += sprintf(buf + len, "T200 Timer: %d\n", pri->timers[PRI_TIMER_T200]);
|
||||
len += sprintf(buf + len, "T203 Timer: %d\n", pri->timers[PRI_TIMER_T203]);
|
||||
len += sprintf(buf + len, "T305 Timer: %d\n", pri->timers[PRI_TIMER_T305]);
|
||||
|
261
pri_facility.c
261
pri_facility.c
@ -1186,6 +1186,198 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
||||
}
|
||||
/* End EECT */
|
||||
|
||||
/* QSIG CF CallRerouting */
|
||||
int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason)
|
||||
{
|
||||
/*CallRerouting ::= OPERATION
|
||||
-- Sent from the Served User PINX to the Rerouting PINX
|
||||
ARGUMENT SEQUENCE
|
||||
{ reroutingReason DiversionReason,
|
||||
originalReroutingReason [0] IMPLICIT DiversionReason OPTIONAL,
|
||||
calledAddress Address,
|
||||
diversionCounter INTEGER (1..15),
|
||||
pSS1InfoElement PSS1InformationElement,
|
||||
-- The basic call information elements Bearer capability, High layer compatibility, Low
|
||||
-- layer compatibity, Progress indicator and Party category can be embedded in the
|
||||
-- pSS1InfoElement in accordance with 6.5.3.1.5
|
||||
lastReroutingNr [1] PresentedNumberUnscreened,
|
||||
subscriptionOption [2] IMPLICIT SubscriptionOption,
|
||||
|
||||
callingPartySubaddress [3] PartySubaddress OPTIONAL,
|
||||
|
||||
callingNumber [4] PresentedNumberScreened,
|
||||
|
||||
callingName [5] Name OPTIONAL,
|
||||
originalCalledNr [6] PresentedNumberUnscreened OPTIONAL,
|
||||
redirectingName [7] Name OPTIONAL,
|
||||
originalCalledName [8] Name OPTIONAL,
|
||||
extension CHOICE {
|
||||
[9] IMPLICIT Extension ,
|
||||
[10] IMPLICIT SEQUENCE OF Extension } OPTIONAL }
|
||||
*/
|
||||
|
||||
int i = 0, j;
|
||||
int res = 0;
|
||||
unsigned char buffer[255] = "";
|
||||
int len = 253;
|
||||
struct rose_component *comp = NULL, *compstk[10];
|
||||
int compsp = 0;
|
||||
static unsigned char op_tag[] = {
|
||||
0x13,
|
||||
};
|
||||
|
||||
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, 2); /* reject - to get feedback from QSIG switch */
|
||||
|
||||
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_INTEGER, &buffer[i], sizeof(buffer)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
|
||||
if (res < 0)
|
||||
return -1;
|
||||
i += res;
|
||||
|
||||
/* call rerouting argument */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* reroutingReason DiversionReason */
|
||||
|
||||
if (reason) {
|
||||
if (!strcasecmp(reason, "cfu"))
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 1); /* cfu */
|
||||
else if (!strcasecmp(reason, "cfb"))
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 2); /* cfb */
|
||||
else if (!strcasecmp(reason, "cfnr"))
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3); /* cfnr */
|
||||
} else {
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0); /* unknown */
|
||||
}
|
||||
|
||||
|
||||
/* calledAddress Address */
|
||||
/* explicit sequence tag for Address */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONSTRUCTOR | ASN1_SEQUENCE), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
/* implicit choice public party number tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
/* type of public party number = unknown */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
|
||||
/* NumberDigits of public party number */
|
||||
j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, (char*)dest, strlen(dest));
|
||||
if (j < 0)
|
||||
return -1;
|
||||
|
||||
i += j;
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
/* diversionCounter INTEGER (1..15) */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer, i, 1);
|
||||
|
||||
/* pSS1InfoElement */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_APPLICATION | ASN1_TAG_0 ), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
buffer[i++] = (0x04); /* add BC */
|
||||
buffer[i++] = (0x03);
|
||||
buffer[i++] = (0x80);
|
||||
buffer[i++] = (0x90);
|
||||
buffer[i++] = (0xa3);
|
||||
buffer[i++] = (0x95);
|
||||
buffer[i++] = (0x32);
|
||||
buffer[i++] = (0x01);
|
||||
buffer[i++] = (0x81);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
/* lastReroutingNr [1]*/
|
||||
/* implicit optional lastReroutingNr tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* implicit choice presented number unscreened tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* implicit choice public party number tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
/* type of public party number = unknown */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 0);
|
||||
j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, original?(char*)original:c->callednum, original?strlen(original):strlen(c->callednum));
|
||||
if (j < 0)
|
||||
return -1;
|
||||
|
||||
i += j;
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
/* subscriptionOption [2]*/
|
||||
/* implicit optional lastReroutingNr tag */
|
||||
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer, i, 0); /* noNotification */
|
||||
|
||||
/* callingNumber [4]*/
|
||||
/* implicit optional callingNumber tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_4), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* implicit choice presented number screened tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_0), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
|
||||
/* implicit choice presentationAllowedAddress tag */
|
||||
ASN1_ADD_SIMPLE(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTOR | ASN1_TAG_1), buffer, i);
|
||||
ASN1_PUSH(compstk, compsp, comp);
|
||||
/* type of public party number = subscriber number */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 4);
|
||||
j = asn1_string_encode(ASN1_NUMERICSTRING, &buffer[i], len - i, 20, c->callernum, strlen(c->callernum));
|
||||
if (j < 0)
|
||||
return -1;
|
||||
|
||||
i += j;
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
/* Screeening Indicator network provided */
|
||||
ASN1_ADD_BYTECOMP(comp, ASN1_ENUMERATED, buffer, i, 3);
|
||||
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
/**/
|
||||
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
ASN1_FIXUP(compstk, compsp, buffer, i);
|
||||
|
||||
res = pri_call_apdu_queue(c, Q931_FACILITY, buffer, i, NULL, NULL);
|
||||
if (res) {
|
||||
pri_message(pri, "Could not queue ADPU 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 QSIG CC-CallRerouting */
|
||||
|
||||
static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_ie *ie)
|
||||
{
|
||||
int res;
|
||||
@ -1215,7 +1407,7 @@ static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_
|
||||
return 0;
|
||||
}
|
||||
/* AFN-PR */
|
||||
extern int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
||||
int anfpr_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 */
|
||||
@ -1548,6 +1740,47 @@ static int aoc_aoce_charging_unit_encode(struct pri *pri, q931_call *c, long cha
|
||||
}
|
||||
/* 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)
|
||||
@ -2158,6 +2391,12 @@ int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, uns
|
||||
pri_message(pri, "Could not parse invoke of type 0x%x!\n", invokeidvalue);
|
||||
return -1;
|
||||
}
|
||||
} else if (pri->switchtype == PRI_SWITCH_QSIG) {
|
||||
switch (invokeidvalue) {
|
||||
case 0x13:
|
||||
if (pri->debug & PRI_DEBUG_APDU) pri_message(pri, "Successfully completed QSIG CF callRerouting!\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
pri_message(pri, "Unable to handle return result on switchtype %d!\n", pri->switchtype);
|
||||
return -1;
|
||||
@ -2209,19 +2448,7 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned c
|
||||
case SS_CNID_CALLINGNAME:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, " Handle Name display operation\n");
|
||||
switch (comp->type) {
|
||||
case ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE:
|
||||
memcpy(call->callername, comp->data, comp->len);
|
||||
call->callername[comp->len] = 0;
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, " Received caller name '%s'\n", call->callername);
|
||||
return 0;
|
||||
default:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "Do not handle argument of type 0x%X\n", comp->type);
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
return rose_calling_name_decode(pri, call, comp, len-i);
|
||||
case ROSE_CALL_TRANSFER_IDENTIFY:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, "ROSE %i: CallTransferIdentify - not handled!\n", operation_tag);
|
||||
@ -2267,8 +2494,10 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned c
|
||||
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
|
||||
return -1;
|
||||
case ROSE_DIVERTING_LEG_INFORMATION2:
|
||||
if (pri->debug & PRI_DEBUG_APDU)
|
||||
pri_message(pri, " Handle DivertingLegInformation2\n");
|
||||
if (pri->debug & PRI_DEBUG_APDU) {
|
||||
pri_message(pri, "ROSE %i: Handle CallingName\n", operation_tag);
|
||||
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
|
||||
}
|
||||
return rose_diverting_leg_information2_decode(pri, call, comp, len-i);
|
||||
case ROSE_AOC_NO_CHARGING_INFO_AVAILABLE:
|
||||
if (pri->debug & PRI_DEBUG_APDU) {
|
||||
|
@ -41,7 +41,10 @@
|
||||
/* Argument values */
|
||||
#define ROSE_NAME_PRESENTATION_ALLOWED_SIMPLE 0x80
|
||||
#define ROSE_NAME_PRESENTATION_RESTRICTED_NULL 0x87
|
||||
#define ROSE_NAME_NOT_AVAIL 0x84
|
||||
#define ROSE_NAME_PRESENTATION_ALLOWED_EXTENDED 0xA1
|
||||
#define ROSE_NAME_PRESENTATION_RESTRICTED_SIMPLE 0xA2
|
||||
#define ROSE_NAME_PRESENTATION_RESTRICTED_EXTENDED 0xA3
|
||||
#define ROSE_NAME_NOT_AVAIL 0x84
|
||||
|
||||
/* Component types */
|
||||
#define COMP_TYPE_INTERPRETATION 0x8B
|
||||
@ -306,8 +309,10 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||
|
||||
int rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||
|
||||
int qsig_cf_callrerouting(struct pri *pri, q931_call *c, const char* dest, const char* original, const char* reason);
|
||||
|
||||
/* starts a QSIG Path Replacement */
|
||||
extern int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||
int anfpr_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||
|
||||
/* Use this function to queue a facility-IE born APDU onto a call
|
||||
* call is the call to use, messagetype is any one of the Q931 messages,
|
||||
|
@ -114,6 +114,9 @@ struct pri {
|
||||
/* do we do overlap dialing */
|
||||
int overlapdial;
|
||||
|
||||
/* do not skip channel 16 */
|
||||
int chan_mapping_logical;
|
||||
|
||||
#ifdef LIBPRI_COUNTERS
|
||||
/* q921/q931 packet counters */
|
||||
unsigned int q921_txcount;
|
||||
|
@ -256,6 +256,8 @@ extern int q931_receive(struct pri *pri, q931_h *h, int len);
|
||||
|
||||
extern int q931_alerting(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
extern int q931_call_progress_with_cause(struct pri *pri, q931_call *call, int channel, int info, int cause);
|
||||
|
||||
extern int q931_call_progress(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
||||
extern int q931_notify(struct pri *pri, q931_call *call, int channel, int info);
|
||||
|
38
q931.c
38
q931.c
@ -345,6 +345,8 @@ static FUNC_RECV(receive_channel_id)
|
||||
pos++;
|
||||
/* Only expect a particular channel */
|
||||
call->channelno = ie->data[pos] & 0x7f;
|
||||
if (pri->chan_mapping_logical && call->channelno > 15)
|
||||
call->channelno++;
|
||||
return 0;
|
||||
}
|
||||
} else
|
||||
@ -400,7 +402,10 @@ static FUNC_SEND(transmit_channel_id)
|
||||
ie->data[pos++] = 0x83;
|
||||
if (call->channelno > -1) {
|
||||
/* Channel number specified */
|
||||
ie->data[pos++] = 0x80 | call->channelno;
|
||||
if (pri->chan_mapping_logical && call->channelno > 16)
|
||||
ie->data[pos++] = 0x80 | (call->channelno - 1);
|
||||
else
|
||||
ie->data[pos++] = 0x80 | call->channelno;
|
||||
return pos + 2;
|
||||
}
|
||||
/* We have to send a channel map */
|
||||
@ -2731,6 +2736,8 @@ int q931_notify(struct pri *pri, q931_call *c, int channel, int info)
|
||||
#ifdef ALERTING_NO_PROGRESS
|
||||
static int call_progress_ies[] = { -1 };
|
||||
#else
|
||||
static int call_progress_with_cause_ies[] = { Q931_PROGRESS_INDICATOR, Q931_CAUSE, -1 };
|
||||
|
||||
static int call_progress_ies[] = { Q931_PROGRESS_INDICATOR, -1 };
|
||||
#endif
|
||||
|
||||
@ -2742,6 +2749,7 @@ int q931_call_progress(struct pri *pri, q931_call *c, int channel, int info)
|
||||
channel &= 0xff;
|
||||
c->channelno = channel;
|
||||
}
|
||||
|
||||
if (info) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
@ -2751,10 +2759,38 @@ int q931_call_progress(struct pri *pri, q931_call *c, int channel, int info)
|
||||
pri_error(pri, "XXX Progress message requested but no information is provided\n");
|
||||
c->progressmask = 0;
|
||||
}
|
||||
|
||||
c->alive = 1;
|
||||
return send_message(pri, c, Q931_PROGRESS, call_progress_ies);
|
||||
}
|
||||
|
||||
int q931_call_progress_with_cause(struct pri *pri, q931_call *c, int channel, int info, int cause)
|
||||
{
|
||||
if (channel) {
|
||||
c->ds1no = (channel & 0xff00) >> 8;
|
||||
c->ds1explicit = (channel & 0x10000) >> 16;
|
||||
channel &= 0xff;
|
||||
c->channelno = channel;
|
||||
}
|
||||
|
||||
if (info) {
|
||||
c->progloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
c->progcode = CODE_CCITT;
|
||||
c->progressmask = PRI_PROG_INBAND_AVAILABLE;
|
||||
} else {
|
||||
/* PI is mandatory IE for PROGRESS message - Q.931 3.1.8 */
|
||||
pri_error(pri, "XXX Progress message requested but no information is provided\n");
|
||||
c->progressmask = 0;
|
||||
}
|
||||
|
||||
c->cause = cause;
|
||||
c->causecode = CODE_CCITT;
|
||||
c->causeloc = LOC_PRIV_NET_LOCAL_USER;
|
||||
|
||||
c->alive = 1;
|
||||
return send_message(pri, c, Q931_PROGRESS, call_progress_with_cause_ies);
|
||||
}
|
||||
|
||||
#ifdef ALERTING_NO_PROGRESS
|
||||
static int call_proceeding_ies[] = { Q931_CHANNEL_IDENT, -1 };
|
||||
#else
|
||||
|
Loading…
Reference in New Issue
Block a user