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:
Matthew Fredrickson
2007-06-06 21:47:36 +00:00
parent f5d76bd5d2
commit bcd84a9d79
5 changed files with 189 additions and 9 deletions

6
pri.c
View File

@@ -544,6 +544,12 @@ int pri_channel_bridge(q931_call *call1, q931_call *call2)
if (call1->pri->switchtype == PRI_SWITCH_DMS100)
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;
}

View File

@@ -1192,6 +1192,162 @@ int eect_initiate_transfer(struct pri *pri, q931_call *c1, q931_call *c2)
}
/* 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 */
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 problemtag = -1;
@@ -1892,7 +2048,7 @@ int rose_reject_decode(struct pri *pri, q931_call *call, unsigned char *data, in
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 errorvalue = -1;
@@ -1956,7 +2112,7 @@ int rose_return_error_decode(struct pri *pri, q931_call *call, unsigned char *da
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 operationidvalue = -1;
@@ -2018,9 +2174,10 @@ int rose_return_result_decode(struct pri *pri, q931_call *call, unsigned char *d
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 res = 0;
int operation_tag;
unsigned char *vdata = data;
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);
}
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:
if (pri->debug & PRI_DEBUG_APDU) {
pri_message(pri, "!! Unable to handle ROSE operation %d", operation_tag);

View File

@@ -9,6 +9,7 @@
#ifndef _PRI_FACILITY_H
#define _PRI_FACILITY_H
#include "pri_q931.h"
/* Protocol Profile field */
#define Q932_PROTOCOL_ROSE 0x11 /* X.219 & X.229 */
@@ -57,6 +58,7 @@
#define ROSE_AOC_IDENTIFICATION_OF_CHARGE 37
/* Q.SIG operations */
#define SS_CNID_CALLINGNAME 0
#define SS_ANFPR_PATHREPLACEMENT 4
#define SS_DIVERTING_LEG_INFORMATION2 21
#define SS_MWI_ACTIVATE 80
#define SS_MWI_DEACTIVATE 81
@@ -254,16 +256,16 @@ struct rose_component {
} while (0)
/* 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 */
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 */
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 */
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);
@@ -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);
/* 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
* 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 */

View File

@@ -246,6 +246,9 @@ struct q931_call {
int transferable;
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);

2
q931.c
View File

@@ -1174,7 +1174,7 @@ static FUNC_RECV(receive_facility)
state = my_state; \
if (pri->debug) \
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;
#define Q932_HANDLE_NULL(component, my_state, name, handle) \
case component: \