parent
6bba2bbfc6
commit
f50bb3fd2d
|
@ -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:
|
||||
===============
|
||||
|
|
29
chan_capi.c
29
chan_capi.c
|
@ -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 }
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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(¶m, "|");
|
||||
srclen = strlen(cidsrc);
|
||||
if (srclen > 20) /* HACK: stop action here, maybe we have invalid data */
|
||||
srclen = 20;
|
||||
|
||||
ciddst = strsep(¶m, "|");
|
||||
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);
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue