- Implementation of Simple Call Transfer
This commit is contained in:
MelwareDE 2007-03-28 19:24:55 +00:00
parent 6bba2bbfc6
commit f50bb3fd2d
7 changed files with 151 additions and 14 deletions

View File

@ -54,6 +54,11 @@ The QSIG support includes:
In dialplan use: Set(__QSIG_SETUP=X) command.
The leading "__" tells asterisk, to export this variable to the outgoing channel and
its subchannels
- Simple Call Transfer
With capicommand(qsig_ct|src-id|dst-id) you can transfer an inbound call back to the qsig switch.
The B-Channel of this call will be relased, so that the line is free for a next call.
Unfortunately the call will be completely released by the switch, if the target is busy.
I have to read the ECMA-300 standard, if there's a chance, to refuse the transfer in such a case.
Future Targets:
===============

View File

@ -145,6 +145,7 @@ static char *commandtdesc = "CAPI command interface.\n"
"\"3pty_begin|${MYHOLDVAR})\" Three-Party-Conference (3PTY) with active and held call\n"
"\"receivefax|filename|stationID|headline\" receive a CAPIfax\n"
"\"sendfax|filename.sff|stationID|headline\" send a CAPIfax\n"
"\"qsig_ct|cidsrc|ciddst\" QSIG call transfer\n"
"Variables set after fax receive:\n"
"FAXSTATUS :0=OK, 1=Error\n"
"FAXREASON :B3 disconnect reason\n"
@ -4793,6 +4794,33 @@ static int pbx_capi_3pty_begin(struct ast_channel *c, char *param)
return 0;
}
/*
* Initiate a QSIG Call Transfer
*/
static int pbx_capi_qsig_ct(struct ast_channel *c, char *param)
{
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
_cmsg CMSG;
struct capi_pvt *i = CC_CHANNEL_PVT(c);
if (!param) { /* no data implies no Calling Number and Destination Number */
cc_log(LOG_WARNING, "capi qsig_ct requires source number and destination number\n");
return -1;
}
cc_qsig_do_facility(fac, c, param, 99);
INFO_REQ_HEADER(&CMSG, capi_ApplID, get_capi_MessageNumber(),0);
INFO_REQ_PLCI(&CMSG) = i->PLCI;
// / *INFO_REQ_FACILITYSELECTOR(&CMSG) = 0;* /
INFO_REQ_FACILITYDATAARRAY(&CMSG) = fac;
_capi_put_cmsg(&CMSG);
return 0;
}
/*
* struct of capi commands
*/
@ -4813,6 +4841,7 @@ static struct capicommands_s {
{ "retrieve", pbx_capi_retrieve, 0 },
{ "ect", pbx_capi_ect, 1 },
{ "3pty_begin", pbx_capi_3pty_begin, 1 },
{ "qsig_ct", pbx_capi_qsig_ct, 1 },
{ NULL, NULL, 0 }
};

View File

@ -136,9 +136,13 @@ struct cc_qsig_nfe {
extern int cc_qsig_build_facility_struct(unsigned char * buf, unsigned int *idx, int apdu_interpr, struct cc_qsig_nfe *nfe);
extern int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke);
extern unsigned int cc_qsig_asn1_get_string(unsigned char *buf, int buflen, unsigned char *data);
extern unsigned int cc_qsig_asn1_get_integer(unsigned char *data, int *idx);
extern unsigned char cc_qsig_asn1_get_oid(unsigned char *data, int *idx);
extern unsigned int cc_qsig_asn1_add_string(unsigned char *buf, int *idx, char *data, int datalen);
extern unsigned int cc_qsig_asn1_add_integer(unsigned char *buf, int *idx, int value);
extern signed int cc_qsig_asn1_check_ecma_isdn_oid(unsigned char *data, int len);
extern unsigned int cc_qsig_check_facility(unsigned char *data, int *idx, int *apduval, int protocol);
extern signed int cc_qsig_check_invoke(unsigned char *data, int *idx);
@ -151,12 +155,17 @@ extern unsigned int cc_qsig_add_call_facility_data(unsigned char *data, struct c
extern signed int cc_qsig_identifyinvoke(struct cc_qsig_invokedata *invoke, int protocol);
extern unsigned int cc_qsig_handle_invokeoperation(int invokeident, struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
extern unsigned int cc_qsig_do_facility(unsigned char *fac, struct ast_channel *c, char *param, unsigned int factype);
/*
*** ECMA QSIG Functions
*/
extern void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
extern int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype);
extern void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
extern void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param);
#endif

View File

@ -88,3 +88,21 @@ unsigned int cc_qsig_asn197ade_get_numdigits(char *buf, int buflen, int *idx, un
/* cc_verbose(1, 1, VERBOSE_PREFIX_4 " * string length %i\n", strsize); */
return strsize;
}
/*
* Returns an string from ASN.1 encoded string
*/
unsigned int cc_qsig_asn197ade_add_numdigits(char *buf, int buflen, int *idx, unsigned char *data)
{
int myidx=0;
if ((1 + buflen) > sizeof(*buf)) {
/* String exceeds buffer size */
return 0;
}
buf[myidx++] = buflen;
memcpy(&buf[myidx], data, buflen);
myidx = 1 + strlen(buf);
return myidx;
}

View File

@ -26,4 +26,6 @@
extern unsigned int cc_qsig_asn197ade_get_partynumber(char *buf, int buflen, int *idx, unsigned char *data);
extern unsigned int cc_qsig_asn197ade_get_numdigits(char *buf, int buflen, int *idx, unsigned char *data);
extern unsigned int cc_qsig_asn197ade_add_numdigits(char *buf, int buflen, int *idx, unsigned char *data);
#endif

View File

@ -218,13 +218,12 @@ int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_in
return -1;
break;
}
if (invoke->datalen > 0) { /* may be no error, if there's no data */
memcpy(&buf[myidx], invoke->data, invoke->datalen);
myidx += invoke->datalen;
}
buf[invlenidx] = myidx-1;
buf[invlenidx] = myidx - invlenidx - 1;
cc_qsig_update_facility_length(buf, myidx - 1);
*idx = myidx;
@ -602,27 +601,27 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
return 0;
}
/*
* Handles outgoing Facilies on Call
* Handles outgoing Facilies on capicommand
*/
unsigned int cc_qsig_add_call_facility_data(unsigned char *data, struct capi_pvt *i, int facility)
unsigned int cc_qsig_do_facility(unsigned char *fac, struct ast_channel *c, char *param, unsigned int factype)
{
/* TODO: Check buffers */
struct cc_qsig_invokedata invoke;
struct cc_qsig_nfe nfe;
unsigned int dataidx;
struct capi_pvt *i = CC_CHANNEL_PVT(c);
/* struct capi_pvt *ii = NULL; */
unsigned int facidx = 0;
/*mg:remember me switch (i->doqsig) {*/
cc_qsig_build_facility_struct(data, &dataidx, APDUINTERPRETATION_IGNORE, &nfe);
switch(facility) {
case 1: /* HACK: Test only */
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 1);
cc_qsig_add_invoke(data, &dataidx, &invoke);
cc_qsig_build_facility_struct(fac, &facidx, APDUINTERPRETATION_REJECT, &nfe);
switch (factype) {
case 99: /* ECMA-300 simpleCallTransfer */
cc_qsig_encode_ecma_sscalltransfer(fac, &facidx, &invoke, i, param);
cc_qsig_add_invoke(fac, &facidx, &invoke);
break;
default:
break;
}
/* }*/
return 0;
}

View File

@ -249,3 +249,78 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap
return;
}
/*
* Encode Operation: 1.3.12.9.99 ECMA/ISDN/SIMPLECALLTRANSFER
*
* This function encodes the simple call transfer facility
*
* We create an invoke struct with the complete encoded invoke.
*
* parameters
* buf is pointer to facility array, not used now
* idx current idx in facility array, not used now
* invoke struct, which contains encoded data for facility
* i is pointer to capi channel
* param is parameter from capicommand
* returns
* always 0
*/
void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
{
const unsigned char oid[] = {0x2b,0x0c,0x09,0x63}; /* 1.3.12.9.99 */
char *cidsrc, *ciddst;
int srclen, dstlen;
int seqlen = 12;
char c[255];
int ix = 0;
cidsrc = strsep(&param, "|");
srclen = strlen(cidsrc);
if (srclen > 20) /* HACK: stop action here, maybe we have invalid data */
srclen = 20;
ciddst = strsep(&param, "|");
dstlen = strlen(ciddst);
if (dstlen > 20) /* HACK: stop action here, maybe we have invalid data */
dstlen = 20;
seqlen += srclen + dstlen;
c[ix++] = ASN1_SEQUENCE | ASN1_TF_CONSTRUCTED; /* start of SEQUENCE */
c[ix++] = seqlen;
c[ix++] = ASN1_TC_CONTEXTSPEC; /* val 1 - Destination CallerID */
c[ix++] = dstlen;
memcpy(&c[ix], ciddst, dstlen);
ix += dstlen;
c[ix++] = ASN1_TC_CONTEXTSPEC | ASN1_TF_CONSTRUCTED; /* val 2 - Source Caller ID struct */
c[ix++] = 5 + srclen;
c[ix++] = ASN1_TC_CONTEXTSPEC; /* CallerID */
c[ix++] = srclen;
memcpy(&c[ix], cidsrc, srclen);
ix += srclen;
c[ix++] = ASN1_ENUMERATED; /* Screening Indicator */
c[ix++] = 1; /* length */
c[ix++] = 1; /* 01 = userProvidedVerifiedAndPassed ...we hope so */
c[ix++] = ASN1_BOOLEAN; /* val 3 - wait for connect ? */
c[ix++] = 1;
c[ix++] = 0;
/* end of SEQUENCE */
/* there are optional data possible here */
invoke->id = 99;
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
invoke->oid_len = sizeof(oid);
memcpy(invoke->oid_bin, oid, sizeof(oid));
invoke->datalen = ix;
memcpy(invoke->data, c, ix);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_CT: %s->%s\n", cidsrc, ciddst);
}