- outbound call transfer
 - outbound path replacement after propose from switch
 - correct handling of outbound QSIG variants
This commit is contained in:
MelwareDE 2007-05-16 18:23:55 +00:00
parent e120f854f0
commit a25c5ee55c
3 changed files with 88 additions and 53 deletions

View File

@ -57,13 +57,25 @@ The QSIG support includes:
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.
If you want need to know, if your target is busy, you can use the call transfer feature below.
- Call Transfer (outgoing)
You can do an outbound call transfer.
First you need the PLCI (logical channel id) of your first channel. You'll get it with capicommand(getplci). This
command returns the channel id in the variable QSIG_PLCI. Now you can enable the call transfer feature.
Simply add "Ct<PLCI>" to QSIG_SETUP (i.e. QSIG_SETUP="X/Ct${QSIG_PLCI}" ). On the next dial command the call will
be automatically transferred. The transfer occurs after the CONNECT. If you want an transfer early on ringing you
can use "Ctr<PLCI>". Then the target user will get the infos about the originating user, while his phone is ringing.
If the external switch offers an path replacement propose, it will be taken automatically in account.
The B-Channels will be cleared by the switch after call connection. Your channels stay free.
Future Targets:
===============
- check code for buffer overflows
- Call Transfer
- Path Replacement
- Call Transfer inbound
- Path Replacement inbound
- Call Rerouting feature [ECMA-174]
- CCBS
- AOC
- ...
@ -73,18 +85,6 @@ How to use:
simply enable Q.SIG with following line in your capi.conf interface:
================================================================================
********** deprecated **********************************************************
#### qsig=on
#### Take care that you enable this only for interfaces, where the other end
#### understands the Q.SIG protocoll. If not, then these switches may reject the
#### entire call, because of wrong facility contents.
#### Later this will change to qsig=off or qsig=1..x where we can support some
#### pbx manufacturer specific operations.
================================================================================
Here we go with new configuration
Set qsig to one of the following values, which corresponds to your configuration.
@ -97,6 +97,4 @@ Set qsig to one of the following values, which corresponds to your configuration
ToDo List:
==========
- Invoke Identifier handling - currently i use invoke id #1, will be corrected by capi (outgoing)
- Handle later facilities - i don't know what to do with most informations now, maybe they are useless in asterisk
- Outgoing calls support only qsig type 1 (Alcatel) - add support for others on outgoing
- Support for inbound routing

View File

@ -263,6 +263,7 @@ struct cc_qsig_data {
unsigned int callmark;
/* Path Replacement */
int pr_propose_sendback; /* send back an prior received PR PROPOSE on Connect */
char *pr_propose_cid; /* Call identity */
char *pr_propose_pn; /* Party Number */

View File

@ -1002,10 +1002,10 @@ void interface_cleanup_qsig(struct capi_pvt *i)
i->qsig_data.partner_ch = NULL;
i->qsig_data.calltransfer_active = 0;
i->qsig_data.calltransfer_onring = 0;
if (i->qsig_data.pr_propose_cid)
free(i->qsig_data.pr_propose_cid);
if (i->qsig_data.pr_propose_pn)
free(i->qsig_data.pr_propose_pn);
if (i->qsig_data.pr_propose_cid)
free(i->qsig_data.pr_propose_cid);
if (i->qsig_data.pr_propose_pn)
free(i->qsig_data.pr_propose_pn);
}
}
@ -1029,27 +1029,37 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
{
unsigned int qsiginvoke;
qsiginvoke = cc_qsig_handle_capi_facilityind( (unsigned char*) INFO_IND_INFOELEMENT(CMSG), i);
/*
if (i->qsig_data.pr_propose_cid && i->qsig_data.pr_propose_pn) {
/* got an Path Replacement */
if ((i->qsig_data.pr_propose_cid && i->qsig_data.pr_propose_pn) &! i->qsig_data.pr_propose_sendback) {
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
if (ii) {
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
cc_qsig_do_facility(fac, i->owner, NULL, 4, 0);
if (ii) {
if (ii->state == CAPI_STATE_CONNECTED) { /* second line is connected, we can proceed */
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
cc_qsig_do_facility(fac, i->owner, NULL, 4, 0);
capi_sendf(NULL, 0, CAPI_INFO_REQ, ii->PLCI, get_capi_MessageNumber(),
"()(()()()s)",
fac
);
} else {
capi_sendf(NULL, 0, CAPI_INFO_REQ, ii->PLCI, get_capi_MessageNumber(),
"()(()()()s)",
fac
);
} else { /* Path Replacement has to be sent back after Connect on second line */
ii->qsig_data.pr_propose_sendback = 1;
ii->qsig_data.pr_propose_cid = strdup(i->qsig_data.pr_propose_cid);
ii->qsig_data.pr_propose_pn = strdup(i->qsig_data.pr_propose_pn);
}
} else
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: no partner channel found (%#x)\n", i->qsig_data.partner_plci);
}
free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
}
*/
}
break;
@ -1110,27 +1120,53 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
case 0x8005: /* SETUP */
break;
case 0x8007: /* CONNECT */
/* {
if (i->qsig_data.pr_propose_cid && i->qsig_data.pr_propose_pn) {
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
if (ii) {
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
cc_qsig_do_facility(fac, i->owner, NULL, 4, 0);
capi_sendf(NULL, 0, CAPI_INFO_REQ, ii->PLCI, get_capi_MessageNumber(),
if (i->qsig_data.calltransfer) {
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
struct capi_pvt *ii = capi_find_interface_by_plci(i->qsig_data.partner_plci);
/* needed for Path Replacement */
ii->qsig_data.partner_plci = i->PLCI;
i->qsig_data.calltransfer = 0;
if (ii) {
cc_qsig_do_facility(fac, ii->owner, NULL, 12, 0);
capi_sendf(NULL, 0, CAPI_INFO_REQ, ii->PLCI, get_capi_MessageNumber(),
"()(()()()s)",
fac
);
cc_qsig_do_facility(fac, i->owner, NULL, 12, 1);
capi_sendf(NULL, 0, CAPI_INFO_REQ, i->PLCI, get_capi_MessageNumber(),
"()(()()()s)",
fac
);
} else {
cc_verbose(1, 1, VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: no partner channel found (%#x)\n", i->qsig_data.partner_plci);
}
free(i->qsig_data.pr_propose_cid);
free(i->qsig_data.pr_propose_pn);
);
} else {
cc_log(LOG_WARNING, "Call Transfer failed - second channel not found (PLCI %#x)!\n", i->qsig_data.partner_plci);
}
}*/
}
{
/* handle prior received Path Replacement */
if ((i->qsig_data.pr_propose_cid && i->qsig_data.pr_propose_pn) && i->qsig_data.pr_propose_sendback) {
unsigned char fac[CAPI_MAX_FACILITYDATAARRAY_SIZE];
cc_qsig_do_facility(fac, i->owner, NULL, 4, 0);
capi_sendf(NULL, 0, CAPI_INFO_REQ, i->PLCI, get_capi_MessageNumber(),
"()(()()()s)",
fac
);
i->qsig_data.pr_propose_sendback = 0;
free(i->qsig_data.pr_propose_cid);
i->qsig_data.pr_propose_cid = NULL;
free(i->qsig_data.pr_propose_pn);
i->qsig_data.pr_propose_pn = NULL;
}
}
break;
case 0x800d: /* SETUP ACK */
break;