@ -609,28 +609,66 @@ static void pbx_capi_qsig_handle_ctc(struct cc_qsig_invokedata *invoke, struct c
struct cc_qsig_ctcomplete ctc ;
struct capi_pvt * ii ;
# define CLEAR_CTC { if (ctc.redirectionNumber.partyNumber) free (ctc.redirectionNumber.partyNumber);\
if ( ctc . basicCallInfoElements ) free ( ctc . basicCallInfoElements ) ; \
if ( ctc . redirectionName ) free ( ctc . redirectionName ) ; \
if ( ctc . argumentExtension ) free ( ctc . argumentExtension ) ; }
# define CLEAR_CTC { if (ctc.redirectionNumber.partyNumber) free _null (ctc.redirectionNumber.partyNumber);\
if ( ctc . basicCallInfoElements ) free _null ( ctc . basicCallInfoElements ) ; \
if ( ctc . redirectionName ) free _null ( ctc . redirectionName ) ; \
if ( ctc . argumentExtension ) free _null ( ctc . argumentExtension ) ; }
int res = cc_qsig_decode_ecma_calltransfer ( invoke , i , & ctc ) ;
if ( ! res )
return ;
if ( ctc . redirectionNumber . partyNumber & & ( ctc . endDesignation = = 2) ) { /* TODO: activate this - there is a problem with channel_masquerade */
if ( ctc . redirectionNumber . partyNumber & & ( ctc . endDesignation = = 0) ) {
ii = capi_find_interface_bynumber ( ctc . redirectionNumber . partyNumber ) ;
if ( ii ) {
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: Call Transfer partner channel for %s found at channel %s \n " , ctc . redirectionNumber . partyNumber , ii - > vname ) ;
char * prpn = i - > qsig_data . if_pr_propose_pn ;
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: Call Transfer partner channel for %s found at channel %s, bridging possible. \n " , ctc . redirectionNumber . partyNumber , ii - > vname ) ;
CLEAR_CTC
if ( ! ( strlen ( prpn ) ) ) {
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: Path Replacement not configured, bridging not available! \n " ) ;
} else {
unsigned char fac [ CAPI_MAX_FACILITYDATAARRAY_SIZE ] ;
ast_channel_masquerade ( i - > owner , ii - > owner ) ;
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: Trying to bridge with Path Replacement number %s... \n " , prpn ) ;
switch ( ii - > state ) {
case CAPI_STATE_ALERTING :
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: peer is in state ALERTING, PATH REPLACE follows after CONNECT... \n " ) ;
ii - > qsig_data . pr_propose_cid = strdup ( " 123 " ) ; /* HACK: need an dynamic ID */
ii - > qsig_data . pr_propose_pn = strdup ( i - > qsig_data . if_pr_propose_pn ) ;
ii - > qsig_data . pr_propose_doinboundbridge = 1 ;
i - > qsig_data . pr_propose_doinboundbridge = 1 ;
i - > qsig_data . partner_plci = ii - > PLCI ;
break ;
case CAPI_STATE_CONNECTED :
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: peer is CONNECTED... \n " ) ;
i - > qsig_data . pr_propose_cid = strdup ( " 123 " ) ; /* HACK: need an dynamic ID */
i - > qsig_data . pr_propose_pn = strdup ( i - > qsig_data . if_pr_propose_pn ) ;
ii - > qsig_data . pr_propose_doinboundbridge = 1 ;
ii - > qsig_data . partner_plci = i - > PLCI ;
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_cid = NULL ;
i - > qsig_data . pr_propose_pn = NULL ;
break ;
default :
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_3 " QSIG: peer's state is %i, which is not handled yet... \n " , ii - > state ) ;
break ;
}
}
CLEAR_CTC
}
}
CLEAR_CTC
CLEAR_CTC
return ;
}
@ -1030,13 +1068,6 @@ int pbx_capi_qsig_ct(struct ast_channel *c, char *param)
return - 1 ;
}
cc_qsig_do_facility ( fac , c , param , 12 , 0 ) ;
capi_sendf ( NULL , 0 , CAPI_INFO_REQ , ii - > PLCI , get_capi_MessageNumber ( ) ,
" ()(()()()s()) " ,
fac
) ;
cc_qsig_do_facility ( fac , c , param , 12 , 1 ) ;
capi_sendf ( NULL , 0 , CAPI_INFO_REQ , i - > PLCI , get_capi_MessageNumber ( ) ,
@ -1044,6 +1075,14 @@ int pbx_capi_qsig_ct(struct ast_channel *c, char *param)
fac
) ;
cc_qsig_do_facility ( fac , c , param , 12 , 0 ) ;
capi_sendf ( NULL , 0 , CAPI_INFO_REQ , ii - > PLCI , get_capi_MessageNumber ( ) ,
" ()(()()()s()) " ,
fac
) ;
return 0 ;
}
@ -1075,13 +1114,13 @@ static void send_feature_calltransfer(struct capi_pvt *i)
ii - > qsig_data . partner_plci = i - > PLCI ;
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 ) ;
cc_qsig_do_facility ( fac , ii - > owner , NULL , 12 , 0 ) ;
capi_sendf ( NULL , 0 , CAPI_INFO_REQ , ii - > PLCI , get_capi_MessageNumber ( ) , " ()(()()()s()) " , fac ) ;
} else {
cc_log ( LOG_WARNING , " Call Transfer failed - second channel not found (PLCI %#x)! \n " , i - > qsig_data . partner_plci ) ;
}
@ -1107,9 +1146,12 @@ void cc_qsig_interface_init(struct cc_capi_conf *conf, struct capi_pvt *tmp)
tmp - > qsig_data . pr_propose_active = 0 ;
tmp - > qsig_data . pr_propose_sendback = 0 ; /* send back an prior received PR PROPOSE on Connect */
tmp - > qsig_data . pr_propose_sentback = 0 ;
tmp - > qsig_data . pr_propose_doinboundbridge = 0 ;
tmp - > qsig_data . pr_propose_cid = NULL ; /* Call identity */
tmp - > qsig_data . pr_propose_pn = NULL ; /* Party Number */
cc_copy_string ( tmp - > qsig_data . if_pr_propose_pn , conf - > qsigconf . if_pr_propose_pn , sizeof ( tmp - > qsig_data . if_pr_propose_pn ) ) ;
/* Partner Channel - needed for many features */
tmp - > qsig_data . partner_ch = NULL ;
tmp - > qsig_data . partner_plci = 0 ;
@ -1118,6 +1160,34 @@ void cc_qsig_interface_init(struct cc_capi_conf *conf, struct capi_pvt *tmp)
ast_cond_init ( & tmp - > qsig_data . event_trigger , NULL ) ;
}
/*
* build the qsig - interface according to configs
*/
void cc_pbx_qsig_conf_interface_value ( struct cc_capi_conf * conf , struct ast_variable * v )
{
# define CONF_STRING(var, token) \
if ( ! strcasecmp ( v - > name , token ) ) { \
cc_copy_string ( var , v - > value , sizeof ( var ) ) ; \
}
# define CONF_INTEGER(var, token) \
if ( ! strcasecmp ( v - > name , token ) ) { \
var = atoi ( v - > value ) ; \
}
# define CONF_TRUE(var, token, val) \
if ( ! strcasecmp ( v - > name , token ) ) { \
if ( ast_true ( v - > value ) ) \
var = val ; \
}
CONF_INTEGER ( conf - > qsigfeat , " qsig " )
CONF_STRING ( conf - > qsigconf . if_pr_propose_pn , " qsig_prnum " )
# undef CONF_STRING
# undef CONF_INTEGER
# undef CONF_TRUE
}
/*
* cleanup QSIG stuff on every ( end of ) call per interface
*/
@ -1129,6 +1199,7 @@ static void qsig_cleanup_channel(struct capi_pvt *i)
i - > qsig_data . calltransfer_onring = 0 ;
i - > qsig_data . pr_propose_active = 0 ;
i - > qsig_data . pr_propose_sentback = 0 ;
i - > qsig_data . pr_propose_doinboundbridge = 0 ;
if ( i - > qsig_data . pr_propose_cid ) {
free ( i - > qsig_data . pr_propose_cid ) ;
i - > qsig_data . pr_propose_cid = NULL ;
@ -1252,7 +1323,7 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
qsiginvoke = cc_qsig_handle_capi_facilityind ( ( unsigned char * ) INFO_IND_INFOELEMENT ( CMSG ) , i ) ;
/* got an Path Replacement */
if ( ( i - > qsig_data . pr_propose_cid & & i - > qsig_data . pr_propose_pn ) & ! i - > qsig_data . pr_propose_sendback ) {
if ( ( i - > qsig_data . pr_propose_cid & & i - > qsig_data . pr_propose_pn ) & ! i - > qsig_data . pr_propose_sendback & ! i - > qsig_data . pr_propose_doinboundbridge ) {
struct capi_pvt * ii = capi_find_interface_by_plci ( i - > qsig_data . partner_plci ) ;
if ( ii ) {
@ -1283,7 +1354,22 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
free ( i - > qsig_data . pr_propose_pn ) ;
i - > qsig_data . pr_propose_pn = NULL ;
}
if ( ( i - > qsig_data . pr_propose_cid & & i - > qsig_data . pr_propose_pn ) & & i - > qsig_data . pr_propose_doinboundbridge ) {
struct ast_channel * chanx ;
struct capi_pvt * ii = capi_find_interface_by_plci ( i - > qsig_data . partner_plci ) ;
if ( ii ) {
cc_verbose ( 1 , 1 , VERBOSE_PREFIX_4 " * QSIG_PATHREPLACEMENT_PROPOSE: trying to complete bridge... \n " ) ;
chanx = ast_bridged_channel ( i - > owner ) ;
ast_channel_masquerade ( ii - > owner , chanx ) ;
}
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 ;
@ -1338,9 +1424,9 @@ void pbx_capi_qsig_handle_info_indication(_cmsg *CMSG, unsigned int PLCI, unsign
) ;
i - > qsig_data . pr_propose_sendback = 0 ;
free ( i - > qsig_data . pr_propose_cid ) ;
free ( i - > qsig_data . pr_propose_cid ) ;
i - > qsig_data . pr_propose_cid = NULL ;
free ( i - > qsig_data . pr_propose_pn ) ;
free ( i - > qsig_data . pr_propose_pn ) ;
i - > qsig_data . pr_propose_pn = NULL ;
i - > qsig_data . pr_propose_sentback = 1 ;
@ -1355,6 +1441,27 @@ 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 ) ;
}
{
/* handle outbound Path Replacement */
if ( ( i - > qsig_data . pr_propose_cid & & i - > qsig_data . pr_propose_pn ) & & i - > qsig_data . pr_propose_doinboundbridge ) {
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 ;
i - > qsig_data . pr_propose_sentback = 1 ;
i - > qsig_data . pr_propose_doinboundbridge = 0 ;
}
}
break ;
case 0x8045 : /* DISCONNECT */
qsig_cleanup_channel ( i ) ;