Preliminary patch plus mods for Q.SIG Path Replacement (Q.SIG version of 2BCT) #7778
git-svn-id: https://origsvn.digium.com/svn/libpri/trunk@422 2fbb986a-6c06-0410-b554-c9c1f0a7f128
This commit is contained in:
6
pri.c
6
pri.c
@@ -544,6 +544,12 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
|
|||||||
if (call1->pri->switchtype == PRI_SWITCH_DMS100)
|
if (call1->pri->switchtype == PRI_SWITCH_DMS100)
|
||||||
return rlt_initiate_transfer(call1->pri, call1, call2);
|
return rlt_initiate_transfer(call1->pri, call1, call2);
|
||||||
|
|
||||||
|
if (call1->pri->switchtype == PRI_SWITCH_QSIG) {
|
||||||
|
call1->bridged_call = call2;
|
||||||
|
call2->bridged_call = call1;
|
||||||
|
return anfpr_initiate_transfer(call1->pri, call1, call2);
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
174
pri_facility.c
174
pri_facility.c
@@ -1192,6 +1192,162 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
|
|||||||
}
|
}
|
||||||
/* End EECT */
|
/* End EECT */
|
||||||
|
|
||||||
|
static int anfpr_pathreplacement_respond(struct pri *pri, q931_call *call, q931_ie *ie)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = pri_call_apdu_queue_cleanup(call->bridged_call);
|
||||||
|
if (res) {
|
||||||
|
pri_message(pri, "Could not Clear queue ADPU\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Send message */
|
||||||
|
res = pri_call_apdu_queue(call->bridged_call, Q931_FACILITY, ie->data, ie->len, 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(call->bridged_call->pri, call->bridged_call);
|
||||||
|
if (res) {
|
||||||
|
pri_message(pri, "Could not schedule facility message for call %d\n", call->bridged_call->cr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* AFN-PR */
|
||||||
|
extern 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 */
|
||||||
|
/* TODO */
|
||||||
|
int i = 0;
|
||||||
|
int res = 0;
|
||||||
|
unsigned char buffer[255] = "";
|
||||||
|
unsigned short call_reference = c2->cr;
|
||||||
|
struct rose_component *comp = NULL, *compstk[10];
|
||||||
|
unsigned char buffer2[255] = "";
|
||||||
|
int compsp = 0;
|
||||||
|
static unsigned char op_tag[] = {
|
||||||
|
0x0C,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Channel 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, 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;
|
||||||
|
|
||||||
|
ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer, i);
|
||||||
|
ASN1_PUSH(compstk, compsp, comp);
|
||||||
|
buffer[i++] = (0x0a);
|
||||||
|
buffer[i++] = (0x01);
|
||||||
|
buffer[i++] = (0x00);
|
||||||
|
buffer[i++] = (0x81);
|
||||||
|
buffer[i++] = (0x00);
|
||||||
|
buffer[i++] = (0x0a);
|
||||||
|
buffer[i++] = (0x01);
|
||||||
|
buffer[i++] = (0x01);
|
||||||
|
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 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(c1->pri, c1);
|
||||||
|
if (res) {
|
||||||
|
pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Channel 2 */
|
||||||
|
i = 0;
|
||||||
|
res = 0;
|
||||||
|
compsp = 0;
|
||||||
|
|
||||||
|
buffer2[i++] = (ASN1_CONTEXT_SPECIFIC | Q932_PROTOCOL_EXTENSIONS);
|
||||||
|
/* Interpretation component */
|
||||||
|
|
||||||
|
ASN1_ADD_SIMPLE(comp, COMP_TYPE_NFE, buffer2, i);
|
||||||
|
ASN1_PUSH(compstk, compsp, comp);
|
||||||
|
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_0), buffer2, i, 0);
|
||||||
|
ASN1_ADD_BYTECOMP(comp, (ASN1_CONTEXT_SPECIFIC | ASN1_TAG_2), buffer2, i, 0);
|
||||||
|
ASN1_FIXUP(compstk, compsp, buffer2, i);
|
||||||
|
|
||||||
|
ASN1_ADD_BYTECOMP(comp, COMP_TYPE_INTERPRETATION, buffer2, i, 2); /* reject */
|
||||||
|
|
||||||
|
ASN1_ADD_SIMPLE(comp, COMP_TYPE_INVOKE, buffer2, i);
|
||||||
|
ASN1_PUSH(compstk, compsp, comp);
|
||||||
|
|
||||||
|
ASN1_ADD_BYTECOMP(comp, ASN1_INTEGER, buffer2, i, get_invokeid(pri));
|
||||||
|
|
||||||
|
res = asn1_string_encode(ASN1_INTEGER, &buffer2[i], sizeof(buffer2)-i, sizeof(op_tag), op_tag, sizeof(op_tag));
|
||||||
|
if (res < 0)
|
||||||
|
return -1;
|
||||||
|
i += res;
|
||||||
|
|
||||||
|
ASN1_ADD_SIMPLE(comp, (ASN1_SEQUENCE | ASN1_CONSTRUCTOR), buffer2, i);
|
||||||
|
ASN1_PUSH(compstk, compsp, comp);
|
||||||
|
buffer2[i++] = (0x0a);
|
||||||
|
buffer2[i++] = (0x01);
|
||||||
|
buffer2[i++] = (0x01);
|
||||||
|
buffer2[i++] = (0x81);
|
||||||
|
buffer2[i++] = (0x00);
|
||||||
|
buffer2[i++] = (0x0a);
|
||||||
|
buffer2[i++] = (0x01);
|
||||||
|
buffer2[i++] = (0x01);
|
||||||
|
ASN1_ADD_WORDCOMP(comp, ASN1_INTEGER, buffer2, i, call_reference);
|
||||||
|
ASN1_FIXUP(compstk, compsp, buffer2, i);
|
||||||
|
ASN1_FIXUP(compstk, compsp, buffer2, i);
|
||||||
|
|
||||||
|
|
||||||
|
res = pri_call_apdu_queue(c2, Q931_FACILITY, buffer2, 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(c2->pri, c2);
|
||||||
|
if (res) {
|
||||||
|
pri_message(pri, "Could not schedule facility message for call %d\n", c1->cr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/* End AFN-PR */
|
||||||
|
|
||||||
/* AOC */
|
/* AOC */
|
||||||
static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
static int aoc_aoce_charging_request_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
@@ -1824,7 +1980,7 @@ static int rose_call_transfer_update_decode(struct pri *pri, q931_call *call, st
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
int rose_reject_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int problemtag = -1;
|
int problemtag = -1;
|
||||||
@@ -1892,7 +2048,7 @@ int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, in
|
|||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
int rose_return_error_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int errorvalue = -1;
|
int errorvalue = -1;
|
||||||
@@ -1956,7 +2112,7 @@ int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *da
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
int rose_return_result_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int operationidvalue = -1;
|
int operationidvalue = -1;
|
||||||
@@ -2018,9 +2174,10 @@ int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *d
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, int len)
|
int rose_invoke_decode(struct pri *pri, q931_call *call, q931_ie *ie, unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
int res = 0;
|
||||||
int operation_tag;
|
int operation_tag;
|
||||||
unsigned char *vdata = data;
|
unsigned char *vdata = data;
|
||||||
struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
|
struct rose_component *comp = NULL, *invokeid = NULL, *operationid = NULL;
|
||||||
@@ -2169,6 +2326,15 @@ int rose_invoke_decode(struct pri *pri, q931_call *call, unsigned char *data, in
|
|||||||
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
|
dump_apdu (pri, (u_int8_t *)comp, comp->len + 2);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
case SS_ANFPR_PATHREPLACEMENT:
|
||||||
|
/* Clear Queue */
|
||||||
|
res = pri_call_apdu_queue_cleanup(call->bridged_call);
|
||||||
|
if (res) {
|
||||||
|
pri_message(pri, "Could not Clear queue ADPU\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
anfpr_pathreplacement_respond(pri, call, ie);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (pri->debug & PRI_DEBUG_APDU) {
|
if (pri->debug & PRI_DEBUG_APDU) {
|
||||||
pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
|
pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#ifndef _PRI_FACILITY_H
|
#ifndef _PRI_FACILITY_H
|
||||||
#define _PRI_FACILITY_H
|
#define _PRI_FACILITY_H
|
||||||
|
#include "pri_q931.h"
|
||||||
|
|
||||||
/* Protocol Profile field */
|
/* Protocol Profile field */
|
||||||
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
|
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
|
||||||
@@ -57,6 +58,7 @@
|
|||||||
#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
|
#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
|
||||||
/* Q.SIG operations */
|
/* Q.SIG operations */
|
||||||
#define SS_CNID_CALLINGNAME 0
|
#define SS_CNID_CALLINGNAME 0
|
||||||
|
#define SS_ANFPR_PATHREPLACEMENT 4
|
||||||
#define SS_DIVERTING_LEG_INFORMATION2 21
|
#define SS_DIVERTING_LEG_INFORMATION2 21
|
||||||
#define SS_MWI_ACTIVATE 80
|
#define SS_MWI_ACTIVATE 80
|
||||||
#define SS_MWI_DEACTIVATE 81
|
#define SS_MWI_DEACTIVATE 81
|
||||||
@@ -254,16 +256,16 @@ struct rose_component {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* Decoder for the invoke ROSE component */
|
/* Decoder for the invoke ROSE component */
|
||||||
int rose_invoke_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
int rose_invoke_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||||
|
|
||||||
/* Decoder for the return result ROSE component */
|
/* Decoder for the return result ROSE component */
|
||||||
int rose_return_result_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
int rose_return_result_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||||
|
|
||||||
/* Decoder for the return error ROSE component */
|
/* Decoder for the return error ROSE component */
|
||||||
int rose_return_error_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
int rose_return_error_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||||
|
|
||||||
/* Decoder for the reject ROSE component */
|
/* Decoder for the reject ROSE component */
|
||||||
int rose_reject_decode(struct pri *pri, struct q931_call *call, unsigned char *data, int len);
|
int rose_reject_decode(struct pri *pri, struct q931_call *call, q931_ie *ie, unsigned char *data, int len);
|
||||||
|
|
||||||
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
|
int asn1_copy_string(char * buf, int buflen, struct rose_component *comp);
|
||||||
|
|
||||||
@@ -284,6 +286,9 @@ 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 rlt_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2);
|
||||||
|
|
||||||
|
/* starts a QSIG Path Replacement */
|
||||||
|
extern 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
|
/* 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,
|
* call is the call to use, messagetype is any one of the Q931 messages,
|
||||||
* apdu is the apdu data, apdu_len is the length of the apdu data */
|
* apdu is the apdu data, apdu_len is the length of the apdu data */
|
||||||
|
|||||||
@@ -246,6 +246,9 @@ struct q931_call {
|
|||||||
|
|
||||||
int transferable;
|
int transferable;
|
||||||
unsigned int rlt_call_id; /* RLT call id */
|
unsigned int rlt_call_id; /* RLT call id */
|
||||||
|
|
||||||
|
/* Bridged call info */
|
||||||
|
q931_call *bridged_call; /* Pointer to other leg of bridged call */
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
extern int pri_schedule_event(struct pri *pri, int ms, void (*function)(void *data), void *data);
|
||||||
|
|||||||
2
q931.c
2
q931.c
@@ -1174,7 +1174,7 @@ static FUNC_RECV(receive_facility)
|
|||||||
state = my_state; \
|
state = my_state; \
|
||||||
if (pri->debug) \
|
if (pri->debug) \
|
||||||
pri_message(pri, "Handle Q.932 %s component\n", name); \
|
pri_message(pri, "Handle Q.932 %s component\n", name); \
|
||||||
(handler)(pri, call, comp->data, comp->len); \
|
(handler)(pri, call, ie, comp->data, comp->len); \
|
||||||
break;
|
break;
|
||||||
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
|
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
|
||||||
case component: \
|
case component: \
|
||||||
|
|||||||
Reference in New Issue
Block a user