- moved more code from chan_capi.c to qsig_core
 - make Call Transfer on alerting state working (wrong number will be displayed on target number at the moment)
This commit is contained in:
MelwareDE 2007-04-19 18:18:42 +00:00
parent 04d4580bc4
commit 9d4968ab3a
4 changed files with 187 additions and 43 deletions

View File

@ -2731,10 +2731,6 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig
case 0x001c: /* Facility Q.932 */
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element FACILITY\n",
i->vname);
if (i->qsigfeat) { /* chances are high, that we got an QSIG Facility */
unsigned int qsiginvoke;
qsiginvoke = cc_qsig_handle_capi_facilityind( (unsigned char*) INFO_IND_INFOELEMENT(CMSG), i);
}
break;
case 0x001e: /* Progress Indicator */
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element PI %02x %02x\n",
@ -2842,9 +2838,6 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig
if (i->owner)
ast_setstate(i->owner, AST_STATE_RINGING);
if (i->qsigfeat) {
/* TODO: some checks, if there's any work here */
}
break;
case 0x8002: /* CALL PROCEEDING */
cc_verbose(3, 1, VERBOSE_PREFIX_3 "%s: info element CALL PROCEEDING\n",
@ -2936,6 +2929,10 @@ static void capidev_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsig
i->vname, INFO_IND_INFONUMBER(CMSG), PLCI);
break;
}
/* QSIG worker - is only executed, if QSIG is enabled */
pbx_capi_qsig_handle_info_indication(CMSG, PLCI, NCCI, i);
return;
}

View File

@ -140,7 +140,7 @@ 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 int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i);
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);
@ -169,6 +169,7 @@ extern int pbx_capi_qsig_ct(struct ast_channel *c, char *param);
extern int pbx_capi_qsig_callmark(struct ast_channel *c, char *param);
extern void interface_cleanup_qsig(struct capi_pvt *i);
extern void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i);
/*
*** ECMA QSIG Functions

View File

@ -183,8 +183,9 @@ int cc_qsig_build_facility_struct(unsigned char * buf, unsigned int *idx, int ap
/*
* Add invoke to buf
*/
int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke)
int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i)
{
unsigned char oid1[] = {0x2b,0x0c,0x09,0x00};
int myidx = *idx;
int invlenidx;
int result;
@ -199,6 +200,26 @@ int cc_qsig_add_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_in
return -1;
}
if (invoke->descr_type == -1) {
switch (i->qsigfeat) {
case QSIG_TYPE_ALCATEL_ECMA:
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
/* Set ECMA/ETSI OID */
oid1[3] = (unsigned char)invoke->type;
invoke->oid_len = sizeof(oid1);
memcpy(invoke->oid_bin, oid1, sizeof(oid1));
break;
case QSIG_TYPE_HICOM_ECMAV2:
invoke->descr_type = ASN1_INTEGER;
/* Leave type as it is */
break;
default:
/* INVOKE is not encoded */
break;
}
}
switch (invoke->descr_type) {
case ASN1_INTEGER:
result = cc_qsig_asn1_add_integer(buf, &myidx, invoke->type);
@ -769,7 +790,7 @@ unsigned int cc_qsig_add_call_setup_data(unsigned char *data, struct capi_pvt *i
/*mg:remember me switch (i->doqsig) {*/
cc_qsig_build_facility_struct(data, &dataidx, APDUINTERPRETATION_IGNORE, &nfe);
cc_qsig_encode_ecma_name_invoke(data, &dataidx, &invoke, i, 0);
cc_qsig_add_invoke(data, &dataidx, &invoke);
cc_qsig_add_invoke(data, &dataidx, &invoke, i);
if (add_externalinfo) {
/* add PROGRESS INDICATOR for external calls*/
@ -796,12 +817,12 @@ unsigned int cc_qsig_do_facility(unsigned char *fac, struct ast_channel *c, cha
switch (factype) {
case 12: /* ECMA-178 callTransfer */
cc_qsig_encode_ecma_calltransfer(fac, &facidx, &invoke, i, param, info1);
cc_qsig_add_invoke(fac, &facidx, &invoke);
cc_qsig_add_invoke(fac, &facidx, &invoke, i);
break;
case 99: /* ECMA-300 simpleCallTransfer */
cc_qsig_encode_ecma_sscalltransfer(fac, &facidx, &invoke, i, param);
cc_qsig_add_invoke(fac, &facidx, &invoke);
cc_qsig_add_invoke(fac, &facidx, &invoke, i);
break;
default:
break;
@ -936,3 +957,124 @@ void interface_cleanup_qsig(struct capi_pvt *i)
}
}
/*
* find the interface (pvt) the PLCI belongs to
*/
static struct capi_pvt *find_interface_by_plci(unsigned int plci)
{
struct capi_pvt *i;
if (plci == 0)
return NULL;
for (i = iflist; i; i = i->next) {
if (i->PLCI == plci)
break;
}
return i;
}
/*
* CAPI INFO_IND (QSIG part)
*/
void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsigned int NCCI, struct capi_pvt *i)
{
if (!i->qsigfeat) /* Run only, if QSIG enabled */
return;
switch(INFO_IND_INFONUMBER(CMSG)) {
case 0x0008: /* Cause */
break;
case 0x0014: /* Call State */
break;
case 0x0018: /* Channel Identification */
break;
case 0x001c: /* Facility Q.932 */
{
unsigned int qsiginvoke;
qsiginvoke = cc_qsig_handle_capi_facilityind( (unsigned char*) INFO_IND_INFOELEMENT(CMSG), i);
}
break;
case 0x001e: /* Progress Indicator */
break;
case 0x0027: /* Notification Indicator */
break;
case 0x0028: /* DSP */
break;
case 0x0029: /* Date/Time */
break;
case 0x0070: /* Called Party Number */
break;
case 0x0074: /* Redirecting Number */
break;
case 0x0076: /* Redirection Number */
break;
case 0x00a1: /* Sending Complete */
break;
case 0x4000: /* CHARGE in UNITS */
break;
case 0x4001: /* CHARGE in CURRENCY */
break;
case 0x8001: /* ALERTING */
/* TODO: some checks, if there's any work here */
if (i->qsig_data.calltransfer_onring) {
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
struct capi_pvt *ii = find_interface_by_plci(i->qsig_data.partner_plci);
_cmsg CMSG3;
i->qsig_data.calltransfer_onring = 0;
if (ii) {
cc_qsig_do_facility(fac, ii->owner, NULL, 12, 0);
INFO_REQ_HEADER(&CMSG3, capi_ApplID, get_capi_MessageNumber(),0);
INFO_REQ_PLCI(&CMSG3) = ii->PLCI;
INFO_REQ_FACILITYDATAARRAY(&CMSG3) = fac;
_capi_put_cmsg(&CMSG3);
cc_qsig_do_facility(fac, i->owner, NULL, 12, 1);
INFO_REQ_HEADER(&CMSG3, capi_ApplID, get_capi_MessageNumber(),0);
INFO_REQ_PLCI(&CMSG3) = i->PLCI;
INFO_REQ_FACILITYDATAARRAY(&CMSG3) = fac;
_capi_put_cmsg(&CMSG3);
} else {
cc_log(LOG_WARNING, "Call Transfer failed - second channel not found (PLCI %#x)!\n", i->qsig_data.partner_plci);
}
}
break;
case 0x8002: /* CALL PROCEEDING */
break;
case 0x8003: /* PROGRESS */
break;
case 0x8005: /* SETUP */
break;
case 0x8007: /* CONNECT */
break;
case 0x800d: /* SETUP ACK */
break;
case 0x800f: /* CONNECT ACK */
break;
case 0x8045: /* DISCONNECT */
break;
case 0x804d: /* RELEASE */
break;
case 0x805a: /* RELEASE COMPLETE */
break;
case 0x8062: /* FACILITY */
break;
case 0x806e: /* NOTIFY */
break;
case 0x807b: /* INFORMATION */
break;
case 0x807d: /* STATUS */
break;
default:
break;
}
return;
}

View File

@ -80,8 +80,6 @@ void cc_qsig_op_ecma_isdn_namepres(struct cc_qsig_invokedata *invoke, struct cap
*/
int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, int nametype)
{
const unsigned char oid[] = {0x2b,0x0c,0x09,0x00}; /* 1.3.12.9.0 */
int oid_len = sizeof(oid);
unsigned char namebuf[51];
unsigned char data[255];
int dataidx = 0;
@ -106,13 +104,12 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
}
invoke->id = 1;
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
invoke->oid_len = oid_len;
memcpy(invoke->oid_bin, oid, oid_len);
invoke->descr_type = -1; /* Let others do the work: qsig_add_invoke */
invoke->type = 0; /* Invoke Operation Number, if OID it's the last byte*/
/* HACK: */
if (nametype)
invoke->oid_bin[3] = 2;
invoke->type = 2;
if (namelen>0) {
data[dataidx++] = 0x80; /* We send only simple Name, Namepresentation allowed */
@ -127,8 +124,7 @@ int cc_qsig_encode_ecma_name_invoke(unsigned char * buf, unsigned int *idx, stru
invoke->datalen = dataidx;
memcpy(invoke->data, data, dataidx);
/* qsig_add_invoke(buf, idx, invoke); */
return 0;
}
@ -270,7 +266,6 @@ void cc_qsig_op_ecma_isdn_leginfo2(struct cc_qsig_invokedata *invoke, struct cap
*/
void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param, int info)
{
const unsigned char oid[] = {0x2b,0x0c,0x09,0xc}; /* 1.3.12.9.12 */
char *cid, *ccanswer;
int icanswer = 0;
int cidlen = 0;
@ -278,22 +273,30 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
char c[255];
int ix = 0;
if (info) {
cid = strsep(&param, "|");
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
if (param) { /* got Call Transfer Parameters */
if (info) {
cid = strsep(&param, "|");
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
} else {
char *tmp = strsep(&param, "|");
tmp = NULL;
cid = strsep(&param, "|");
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
ccanswer = strsep(&param, "|");
if (ccanswer[0])
icanswer = ccanswer[0] - 0x30;
}
} else {
char *tmp = strsep(&param, "|");
tmp = NULL;
cid = strsep(&param, "|");
cid = strdup(i->owner->cid.cid_num);
cidlen = strlen(cid);
if (cidlen > 20) /* HACK: stop action here, maybe we have invalid data */
cidlen = 20;
ccanswer = strsep(&param, "|");
if (ccanswer[0])
icanswer = ccanswer[0] - 0x30;
if (!info)
icanswer = i->qsig_data.calltransfer_onring % 1;
}
seqlen += cidlen;
@ -324,16 +327,19 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
/* there are optional data possible here */
invoke->id = 12;
invoke->descr_type = ASN1_OBJECTIDENTIFIER;
invoke->oid_len = sizeof(oid);
memcpy(invoke->oid_bin, oid, sizeof(oid));
invoke->descr_type = -1;
invoke->type = 12; /* Invoke Operation Code */
invoke->datalen = ix;
memcpy(invoke->data, c, ix);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_CT: %i->%s\n", info, cid);
if (cid)
free(cid);
}
/*
* Encode Operation: 1.3.12.9.99 ECMA/ISDN/SINGLESTEPCALLTRANSFER
*
@ -352,7 +358,6 @@ void cc_qsig_encode_ecma_calltransfer(unsigned char * buf, unsigned int *idx, st
*/
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;
@ -398,10 +403,9 @@ void cc_qsig_encode_ecma_sscalltransfer(unsigned char * buf, unsigned int *idx,
/* 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->descr_type = -1;
invoke->type = 99;
invoke->datalen = ix;
memcpy(invoke->data, c, ix);
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_SSCT: %s->%s\n", cidsrc, ciddst);
@ -498,7 +502,7 @@ void cc_qsig_op_ecma_isdn_prpropose(struct cc_qsig_invokedata *invoke, struct ca
void cc_qsig_encode_ecma_prpropose(unsigned char * buf, unsigned int *idx, struct cc_qsig_invokedata *invoke, struct capi_pvt *i, char *param)
{
/* TODO: write code */
const unsigned char oid[] = {0x2b,0x0c,0x09,0x13}; /* 1.3.12.9.99 */
// int invokeop = 19;
return;
}