2007-05-06 13:54:52 +00:00
/*****************************************************************************\
* * * *
2007-07-17 17:28:09 +00:00
* * Linux Call Router * *
2007-05-06 13:54:52 +00:00
* * * *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * Copyright : Andreas Eversberg * *
* * * *
2007-07-17 17:28:09 +00:00
* * join functions * *
2007-05-06 13:54:52 +00:00
* * * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "main.h"
2008-05-01 08:35:20 +00:00
//#define __u8 unsigned char
//#define __u16 unsigned short
2008-06-14 06:34:50 +00:00
//#define __u32 unsigned int
2007-05-06 13:54:52 +00:00
/* notify endpoint about state change (if any) */
2007-07-17 17:28:09 +00:00
static int notify_state_change ( int join_id , int epoint_id , int old_state , int new_state )
2007-05-06 13:54:52 +00:00
{
int notify_off = 0 , notify_on = 0 ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
if ( old_state = = new_state )
return ( old_state ) ;
2009-07-05 20:14:21 +00:00
switch ( old_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_ACTIVE :
2009-07-05 20:14:21 +00:00
switch ( new_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_HOLD :
notify_on = INFO_NOTIFY_REMOTE_HOLD ;
break ;
case NOTIFY_STATE_SUSPEND :
notify_on = INFO_NOTIFY_USER_SUSPENDED ;
break ;
case NOTIFY_STATE_CONFERENCE :
notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED ;
break ;
}
break ;
case NOTIFY_STATE_HOLD :
2009-07-05 20:14:21 +00:00
switch ( new_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_ACTIVE :
notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL ;
break ;
case NOTIFY_STATE_SUSPEND :
notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL ;
notify_on = INFO_NOTIFY_USER_SUSPENDED ;
break ;
case NOTIFY_STATE_CONFERENCE :
notify_off = INFO_NOTIFY_REMOTE_RETRIEVAL ;
notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED ;
break ;
}
break ;
case NOTIFY_STATE_SUSPEND :
2009-07-05 20:14:21 +00:00
switch ( new_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_ACTIVE :
notify_off = INFO_NOTIFY_USER_RESUMED ;
break ;
case NOTIFY_STATE_HOLD :
notify_off = INFO_NOTIFY_USER_RESUMED ;
notify_on = INFO_NOTIFY_REMOTE_HOLD ;
break ;
case NOTIFY_STATE_CONFERENCE :
notify_off = INFO_NOTIFY_USER_RESUMED ;
notify_on = INFO_NOTIFY_CONFERENCE_ESTABLISHED ;
break ;
}
break ;
case NOTIFY_STATE_CONFERENCE :
2009-07-05 20:14:21 +00:00
switch ( new_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_ACTIVE :
notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED ;
break ;
case NOTIFY_STATE_HOLD :
notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED ;
notify_on = INFO_NOTIFY_REMOTE_HOLD ;
break ;
case NOTIFY_STATE_SUSPEND :
notify_off = INFO_NOTIFY_CONFERENCE_DISCONNECTED ;
notify_on = INFO_NOTIFY_USER_SUSPENDED ;
break ;
}
break ;
}
2009-07-05 20:14:21 +00:00
if ( join_id & & notify_off ) {
2007-07-17 17:28:09 +00:00
message = message_create ( join_id , epoint_id , JOIN_TO_EPOINT , MESSAGE_NOTIFY ) ;
2007-05-06 13:54:52 +00:00
message - > param . notifyinfo . notify = notify_off ;
message_put ( message ) ;
}
2009-07-05 20:14:21 +00:00
if ( join_id & & notify_on ) {
2007-07-17 17:28:09 +00:00
message = message_create ( join_id , epoint_id , JOIN_TO_EPOINT , MESSAGE_NOTIFY ) ;
2007-05-06 13:54:52 +00:00
message - > param . notifyinfo . notify = notify_on ;
message_put ( message ) ;
}
return ( new_state ) ;
}
2007-07-17 17:28:09 +00:00
/* debug function for join */
2008-09-02 00:02:11 +00:00
void joinpbx_debug ( class JoinPBX * joinpbx , const char * function )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation ;
2007-05-06 13:54:52 +00:00
struct port_list * portlist ;
class Endpoint * epoint ;
class Port * port ;
char buffer [ 512 ] ;
2007-07-17 17:28:09 +00:00
if ( ! ( options . deb & DEBUG_JOIN ) )
2007-05-06 13:54:52 +00:00
return ;
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join(%d) start (called from %s) \n " , joinpbx - > j_serial , function ) ;
2007-05-06 13:54:52 +00:00
2007-07-26 12:23:56 +00:00
relation = joinpbx - > j_relation ;
2007-05-06 13:54:52 +00:00
if ( ! relation )
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " join has no relations \n " ) ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-05-06 13:54:52 +00:00
epoint = find_epoint_id ( relation - > epoint_id ) ;
2009-07-05 20:14:21 +00:00
if ( ! epoint ) {
2008-07-29 17:00:12 +00:00
PDEBUG ( DEBUG_JOIN , " warning: relations epoint id=%d doesn't exists! \n " , relation - > epoint_id ) ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
continue ;
}
buffer [ 0 ] = ' \0 ' ;
2008-07-29 17:00:12 +00:00
UPRINT ( strchr ( buffer , 0 ) , " *** ep%d " , relation - > epoint_id ) ;
2007-05-06 13:54:52 +00:00
UPRINT ( strchr ( buffer , 0 ) , " ifs= " ) ;
portlist = epoint - > ep_portlist ;
2009-07-05 20:14:21 +00:00
while ( portlist ) {
2007-05-06 13:54:52 +00:00
port = find_port_id ( portlist - > port_id ) ;
if ( port )
UPRINT ( strchr ( buffer , 0 ) , " %s, " , port - > p_name ) ;
else
2008-07-29 17:00:12 +00:00
UPRINT ( strchr ( buffer , 0 ) , " <port %d doesn't exist>, " , portlist - > port_id ) ;
2007-05-06 13:54:52 +00:00
portlist = portlist - > next ;
}
2007-07-26 12:23:56 +00:00
// UPRINT(strchr(buffer,0), " endpoint=%d on=%s hold=%s", epoint->ep_serial, (epoint->ep_join_id==joinpbx->j_serial)?"yes":"no", (epoint->get_hold_id()==joinpbx->j_serial)?"yes":"no");
UPRINT ( strchr ( buffer , 0 ) , " endpoint=%d on=%s " , epoint - > ep_serial , ( epoint - > ep_join_id = = joinpbx - > j_serial ) ? " yes " : " no " ) ;
2009-07-05 20:14:21 +00:00
switch ( relation - > type ) {
2007-05-06 13:54:52 +00:00
case RELATION_TYPE_CALLING :
UPRINT ( strchr ( buffer , 0 ) , " type=CALLING " ) ;
break ;
case RELATION_TYPE_SETUP :
UPRINT ( strchr ( buffer , 0 ) , " type=SETUP " ) ;
break ;
case RELATION_TYPE_CONNECT :
UPRINT ( strchr ( buffer , 0 ) , " type=CONNECT " ) ;
break ;
default :
UPRINT ( strchr ( buffer , 0 ) , " type=unknown " ) ;
break ;
}
2008-05-25 14:12:20 +00:00
if ( relation - > channel_state )
2007-05-06 13:54:52 +00:00
UPRINT ( strchr ( buffer , 0 ) , " channel=CONNECT " ) ;
2008-05-25 14:12:20 +00:00
else
2007-05-06 13:54:52 +00:00
UPRINT ( strchr ( buffer , 0 ) , " channel=HOLD " ) ;
2009-07-05 20:14:21 +00:00
switch ( relation - > tx_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_ACTIVE :
UPRINT ( strchr ( buffer , 0 ) , " tx_state=ACTIVE " ) ;
break ;
case NOTIFY_STATE_HOLD :
UPRINT ( strchr ( buffer , 0 ) , " tx_state=HOLD " ) ;
break ;
case NOTIFY_STATE_SUSPEND :
UPRINT ( strchr ( buffer , 0 ) , " tx_state=SUSPEND " ) ;
break ;
case NOTIFY_STATE_CONFERENCE :
UPRINT ( strchr ( buffer , 0 ) , " tx_state=CONFERENCE " ) ;
break ;
default :
UPRINT ( strchr ( buffer , 0 ) , " tx_state=unknown " ) ;
break ;
}
2009-07-05 20:14:21 +00:00
switch ( relation - > rx_state ) {
2007-05-06 13:54:52 +00:00
case NOTIFY_STATE_ACTIVE :
UPRINT ( strchr ( buffer , 0 ) , " rx_state=ACTIVE " ) ;
break ;
case NOTIFY_STATE_HOLD :
UPRINT ( strchr ( buffer , 0 ) , " rx_state=HOLD " ) ;
break ;
case NOTIFY_STATE_SUSPEND :
UPRINT ( strchr ( buffer , 0 ) , " rx_state=SUSPEND " ) ;
break ;
case NOTIFY_STATE_CONFERENCE :
UPRINT ( strchr ( buffer , 0 ) , " rx_state=CONFERENCE " ) ;
break ;
default :
UPRINT ( strchr ( buffer , 0 ) , " rx_state=unknown " ) ;
break ;
}
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " %s \n " , buffer ) ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
}
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " end \n " ) ;
2007-05-06 13:54:52 +00:00
}
2010-01-16 10:20:23 +00:00
int update_bridge ( struct lcr_work * work , void * instance , int index ) ;
2007-05-06 13:54:52 +00:00
/*
2007-07-17 17:28:09 +00:00
* constructor for a new join
* the join will have a relation to the calling endpoint
2007-05-06 13:54:52 +00:00
*/
2007-07-17 17:28:09 +00:00
JoinPBX : : JoinPBX ( class Endpoint * epoint ) : Join ( )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation ;
2007-05-06 13:54:52 +00:00
// char filename[256];
if ( ! epoint )
2007-07-15 10:01:27 +00:00
FATAL ( " epoint is NULL. \n " ) ;
2007-05-06 13:54:52 +00:00
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " creating new join and connecting it to the endpoint. \n " ) ;
2007-05-06 13:54:52 +00:00
2007-07-26 12:23:56 +00:00
j_type = JOIN_TYPE_PBX ;
j_caller [ 0 ] = ' \0 ' ;
j_caller_id [ 0 ] = ' \0 ' ;
j_dialed [ 0 ] = ' \0 ' ;
j_todial [ 0 ] = ' \0 ' ;
j_pid = getpid ( ) ;
j_partyline = 0 ;
2007-09-10 05:10:50 +00:00
j_partyline_jingle = 0 ;
2012-07-29 10:18:02 +00:00
j_3pty = 0 ;
2007-07-31 05:34:18 +00:00
j_multicause = 0 ;
j_multilocation = 0 ;
2010-01-16 10:20:23 +00:00
memset ( & j_updatebridge , 0 , sizeof ( j_updatebridge ) ) ;
add_work ( & j_updatebridge , update_bridge , this , 0 ) ;
2007-05-06 13:54:52 +00:00
/* initialize a relation only to the calling interface */
2007-07-26 12:23:56 +00:00
relation = j_relation = ( struct join_relation * ) MALLOC ( sizeof ( struct join_relation ) ) ;
2007-05-06 13:54:52 +00:00
cmemuse + + ;
relation - > type = RELATION_TYPE_CALLING ;
2008-05-25 14:12:20 +00:00
relation - > channel_state = 0 ; /* audio is assumed on a new join */
2007-07-17 17:28:09 +00:00
relation - > tx_state = NOTIFY_STATE_ACTIVE ; /* new joins always assumed to be active */
relation - > rx_state = NOTIFY_STATE_ACTIVE ; /* new joins always assumed to be active */
2007-05-06 13:54:52 +00:00
relation - > epoint_id = epoint - > ep_serial ;
2007-07-17 17:28:09 +00:00
if ( options . deb & DEBUG_JOIN )
joinpbx_debug ( this , " JoinPBX::Constructor(new join) " ) ;
2007-05-06 13:54:52 +00:00
}
/*
2007-07-17 17:28:09 +00:00
* join descructor
2007-05-06 13:54:52 +00:00
*/
2007-07-17 17:28:09 +00:00
JoinPBX : : ~ JoinPBX ( )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation , * rtemp ;
2007-05-06 13:54:52 +00:00
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-05-06 13:54:52 +00:00
rtemp = relation - > next ;
2007-07-17 17:28:09 +00:00
FREE ( relation , sizeof ( struct join_relation ) ) ;
2007-05-06 13:54:52 +00:00
cmemuse - - ;
relation = rtemp ;
}
2010-01-16 10:20:23 +00:00
2012-07-29 10:18:02 +00:00
/* remove 3PTY from other join */
if ( j_3pty ) {
class Join * join ;
class JoinPBX * joinpbx ;
join = find_join_id ( j_3pty ) ;
if ( join & & join - > j_type = = JOIN_TYPE_PBX ) {
joinpbx = ( class JoinPBX * ) join ;
joinpbx - > j_3pty = 0 ;
trigger_work ( & joinpbx - > j_updatebridge ) ;
}
}
2010-01-16 10:20:23 +00:00
del_work ( & j_updatebridge ) ;
2007-05-06 13:54:52 +00:00
}
2007-07-17 17:28:09 +00:00
/* bridge sets the audio flow of all bchannels assiociated to 'this' join
2007-05-15 20:59:29 +00:00
* also it changes and notifies active / hold / conference states
2007-05-06 13:54:52 +00:00
*/
2010-01-16 10:20:23 +00:00
int update_bridge ( struct lcr_work * work , void * instance , int index )
{
class JoinPBX * joinpbx = ( class JoinPBX * ) instance ;
joinpbx - > bridge ( ) ;
return 0 ;
}
2007-07-17 17:28:09 +00:00
void JoinPBX : : bridge ( void )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-15 20:59:29 +00:00
int numconnect = 0 , relations = 0 ;
2007-05-06 13:54:52 +00:00
class Endpoint * epoint ;
struct port_list * portlist ;
class Port * port ;
2012-07-29 10:18:02 +00:00
unsigned int bridge_id ;
2012-12-08 09:58:47 +00:00
class Join * join_3pty ;
class JoinPBX * joinpbx_3pty ;
2007-07-15 10:01:27 +00:00
# ifdef DEBUG_COREBRIDGE
int allmISDN = 0 ; // never set for debug purpose
# else
int allmISDN = 1 ; // set until a non-mISDN relation is found
# endif
2007-05-06 13:54:52 +00:00
2012-07-29 10:18:02 +00:00
/* bridge id is the serial of join
* if we have a 3 pty with another join , we always use the lowest brigde id .
* this way we use common ids , so both joins share same bridge */
if ( j_3pty & & j_3pty < j_serial )
bridge_id = j_3pty ;
else
bridge_id = j_serial ;
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-05-15 20:59:29 +00:00
/* count all relations */
relations + + ;
/* check for relation's objects */
2007-05-06 13:54:52 +00:00
epoint = find_epoint_id ( relation - > epoint_id ) ;
2009-07-05 20:14:21 +00:00
if ( ! epoint ) {
2007-05-06 13:54:52 +00:00
PERROR ( " software error: relation without existing endpoints. \n " ) ;
relation = relation - > next ;
continue ;
}
portlist = epoint - > ep_portlist ;
2009-07-05 20:14:21 +00:00
if ( ! portlist ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d ignoring relation without port object. \n " , j_serial ) ;
2007-05-06 13:54:52 +00:00
//#warning testing: keep on hold until single audio stream available
2008-05-25 14:12:20 +00:00
relation - > channel_state = 0 ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
continue ;
}
2009-07-05 20:14:21 +00:00
if ( portlist - > next ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d ignoring relation with ep%d due to port_list. \n " , j_serial , epoint - > ep_serial ) ;
2007-05-06 13:54:52 +00:00
//#warning testing: keep on hold until single audio stream available
2008-05-25 14:12:20 +00:00
relation - > channel_state = 0 ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
continue ;
}
port = find_port_id ( portlist - > port_id ) ;
2009-07-05 20:14:21 +00:00
if ( ! port ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d ignoring relation without existing port object. \n " , j_serial ) ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
continue ;
}
2009-07-05 20:14:21 +00:00
if ( ( port - > p_type & PORT_CLASS_MASK ) ! = PORT_CLASS_mISDN ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d ignoring relation ep%d because it's port is not mISDN. \n " , j_serial , epoint - > ep_serial ) ;
2009-07-05 20:14:21 +00:00
if ( allmISDN ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d not all endpoints are mISDN. \n " , j_serial ) ;
2007-05-15 20:59:29 +00:00
allmISDN = 0 ;
2007-05-06 13:54:52 +00:00
}
relation = relation - > next ;
continue ;
}
2012-12-23 05:45:43 +00:00
# ifdef WITH_VOOTP
if ( port - > p_vootp ) {
PDEBUG ( DEBUG_JOIN , " join%d ignoring relation ep%d because it's port uses VoOTP. \n " , j_serial , epoint - > ep_serial ) ;
if ( allmISDN ) {
PDEBUG ( DEBUG_JOIN , " join%d not all endpoints can support mISDN bridging. \n " , j_serial ) ;
allmISDN = 0 ;
}
relation = relation - > next ;
continue ;
}
# endif
2012-12-08 09:58:47 +00:00
2007-05-15 20:59:29 +00:00
relation = relation - > next ;
}
2012-12-08 09:58:47 +00:00
/* check if 3pty members have no mISDN, so bridging via mISDN/lcr will be selected correctly */
join_3pty = find_join_id ( j_3pty ) ;
if ( join_3pty & & join_3pty - > j_type = = JOIN_TYPE_PBX ) {
joinpbx_3pty = ( class JoinPBX * ) join_3pty ;
relation = joinpbx_3pty - > j_relation ;
while ( relation ) {
#if 0
no need to count , because j_3pty is taken into account below when checking relations
/* count all relations */
relations + + ;
# endif
/* check for relation's objects */
epoint = find_epoint_id ( relation - > epoint_id ) ;
if ( ! epoint ) {
PERROR ( " software error: relation without existing endpoints. \n " ) ;
relation = relation - > next ;
continue ;
}
portlist = epoint - > ep_portlist ;
if ( ! portlist ) {
PDEBUG ( DEBUG_JOIN , " other 3pty join %d: ignoring relation without port object. \n " , joinpbx_3pty - > j_serial ) ;
//#warning testing: keep on hold until single audio stream available
relation - > channel_state = 0 ;
relation = relation - > next ;
continue ;
}
if ( portlist - > next ) {
PDEBUG ( DEBUG_JOIN , " other 3pty join %d: ignoring relation with ep%d due to port_list. \n " , joinpbx_3pty - > j_serial , epoint - > ep_serial ) ;
//#warning testing: keep on hold until single audio stream available
relation - > channel_state = 0 ;
relation = relation - > next ;
continue ;
}
port = find_port_id ( portlist - > port_id ) ;
if ( ! port ) {
PDEBUG ( DEBUG_JOIN , " other 3pty join %d: ignoring relation without existing port object. \n " , joinpbx_3pty - > j_serial ) ;
relation = relation - > next ;
continue ;
}
if ( ( port - > p_type & PORT_CLASS_MASK ) ! = PORT_CLASS_mISDN ) {
PDEBUG ( DEBUG_JOIN , " other 3pty join %d: ignoring relation ep%d because it's port is not mISDN. \n " , joinpbx_3pty - > j_serial , epoint - > ep_serial ) ;
if ( allmISDN ) {
PDEBUG ( DEBUG_JOIN , " other 3pty join %d: not all endpoints are mISDN. \n " , joinpbx_3pty - > j_serial ) ;
allmISDN = 0 ;
}
relation = relation - > next ;
continue ;
}
2012-12-23 05:45:43 +00:00
# ifdef WITH_VOOTP
if ( port - > p_vootp ) {
PDEBUG ( DEBUG_JOIN , " join%d ignoring relation ep%d because it's port uses VoOTP. \n " , joinpbx_3pty - > j_serial , epoint - > ep_serial ) ;
if ( allmISDN ) {
PDEBUG ( DEBUG_JOIN , " join%d not all endpoints can support mISDN bridging. \n " , joinpbx_3pty - > j_serial ) ;
allmISDN = 0 ;
}
relation = relation - > next ;
continue ;
}
# endif
2012-12-08 09:58:47 +00:00
relation = relation - > next ;
}
}
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d members=%d %s \n " , j_serial , relations , ( allmISDN ) ? " (all are mISDN-members) " : " (not all are mISDN-members) " ) ;
2007-05-15 20:59:29 +00:00
/* we notify all relations about rxdata. */
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-05-15 20:59:29 +00:00
/* count connected relations */
2008-05-25 14:12:20 +00:00
if ( ( relation - > channel_state = = 1 )
2007-05-15 20:59:29 +00:00
& & ( relation - > rx_state ! = NOTIFY_STATE_SUSPEND )
& & ( relation - > rx_state ! = NOTIFY_STATE_HOLD ) )
numconnect + + ;
/* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */
2012-07-29 10:18:02 +00:00
/* mISDN */
2008-05-25 14:12:20 +00:00
if ( relation - > channel_state = = 1
2007-05-06 13:54:52 +00:00
& & relation - > rx_state ! = NOTIFY_STATE_HOLD
2007-05-15 20:59:29 +00:00
& & relation - > rx_state ! = NOTIFY_STATE_SUSPEND
2007-07-08 09:24:26 +00:00
& & relations > 1 // no conf with one member
2009-07-05 20:14:21 +00:00
& & allmISDN ) { // no conf if any member is not mISDN
2007-07-26 12:23:56 +00:00
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , MESSAGE_mISDNSIGNAL ) ;
2007-05-06 13:54:52 +00:00
message - > param . mISDNsignal . message = mISDNSIGNAL_CONF ;
2012-07-29 10:18:02 +00:00
message - > param . mISDNsignal . conf = ( bridge_id < < 16 ) | j_pid ;
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d EP%d +on+ id: 0x%08x \n " , j_serial , relation - > epoint_id , message - > param . mISDNsignal . conf ) ;
2007-05-06 13:54:52 +00:00
message_put ( message ) ;
2009-07-05 20:14:21 +00:00
} else {
2007-07-26 12:23:56 +00:00
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , MESSAGE_mISDNSIGNAL ) ;
2007-05-06 13:54:52 +00:00
message - > param . mISDNsignal . message = mISDNSIGNAL_CONF ;
message - > param . mISDNsignal . conf = 0 ;
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d EP%d +off+ id: 0x%08x \n " , j_serial , relation - > epoint_id , message - > param . mISDNsignal . conf ) ;
2007-05-06 13:54:52 +00:00
message_put ( message ) ;
}
2007-05-15 20:59:29 +00:00
2012-07-29 10:18:02 +00:00
/* core bridge */
if ( relation - > channel_state = = 1
& & relation - > rx_state ! = NOTIFY_STATE_HOLD
& & relation - > rx_state ! = NOTIFY_STATE_SUSPEND
& & relations > 1 // no bridge with one member
& & ! allmISDN ) { // no bridge if all members are mISDN
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , MESSAGE_BRIDGE ) ;
message - > param . bridge_id = bridge_id ;
PDEBUG ( DEBUG_JOIN , " join%u EP%u requests bridge=%u \n " , j_serial , relation - > epoint_id , bridge_id ) ;
message_put ( message ) ;
} else {
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , MESSAGE_BRIDGE ) ;
message - > param . bridge_id = 0 ;
PDEBUG ( DEBUG_JOIN , " join%u EP%u drop bridge=%u \n " , j_serial , relation - > epoint_id , bridge_id ) ;
message_put ( message ) ;
}
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
}
2007-05-15 20:59:29 +00:00
/* two people just exchange their states */
2012-07-29 10:18:02 +00:00
if ( ! j_3pty & & relations = = 2 & & ! j_partyline ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " join%d 2 relations / no partyline \n " , j_serial ) ;
relation = j_relation ;
relation - > tx_state = notify_state_change ( j_serial , relation - > epoint_id , relation - > tx_state , relation - > next - > rx_state ) ;
relation - > next - > tx_state = notify_state_change ( j_serial , relation - > next - > epoint_id , relation - > next - > tx_state , relation - > rx_state ) ;
2007-05-06 13:54:52 +00:00
} else
2007-07-17 17:28:09 +00:00
/* one member in a join, so we put her on hold */
2012-07-29 10:18:02 +00:00
if ( ! j_3pty & & ( relations = = 1 | | numconnect = = 1 ) /* && !j_partyline_jingle*/ ) {
2008-05-12 16:35:48 +00:00
PDEBUG ( DEBUG_JOIN , " join%d 1 member or only 1 connected, put on hold \n " , j_serial ) ;
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2008-05-25 14:12:20 +00:00
if ( ( relation - > channel_state = = 1 )
2007-05-06 13:54:52 +00:00
& & ( relation - > rx_state ! = NOTIFY_STATE_SUSPEND )
& & ( relation - > rx_state ! = NOTIFY_STATE_HOLD ) )
2007-07-26 12:23:56 +00:00
relation - > tx_state = notify_state_change ( j_serial , relation - > epoint_id , relation - > tx_state , NOTIFY_STATE_HOLD ) ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
}
2009-07-05 20:14:21 +00:00
} else {
2007-09-10 05:10:50 +00:00
/* if conference/partyline (or more than two members and more than one is connected), so we set conference state */
2008-05-12 16:35:48 +00:00
PDEBUG ( DEBUG_JOIN , " join%d %d members, %d connected, signal conference \n " , j_serial , relations , numconnect ) ;
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2008-05-25 14:12:20 +00:00
if ( ( relation - > channel_state = = 1 )
2007-05-06 13:54:52 +00:00
& & ( relation - > rx_state ! = NOTIFY_STATE_SUSPEND )
& & ( relation - > rx_state ! = NOTIFY_STATE_HOLD ) )
2007-07-26 12:23:56 +00:00
relation - > tx_state = notify_state_change ( j_serial , relation - > epoint_id , relation - > tx_state , NOTIFY_STATE_CONFERENCE ) ;
2007-05-06 13:54:52 +00:00
relation = relation - > next ;
}
}
}
2007-07-17 17:28:09 +00:00
/* release join from endpoint
* if the join has two relations , all relations are freed and the join will be
2007-07-15 10:01:27 +00:00
* destroyed
* on outgoing relations , the cause is collected , if not connected
2007-07-17 17:28:09 +00:00
* returns if join has been destroyed
2007-05-06 13:54:52 +00:00
*/
2007-07-17 17:28:09 +00:00
int JoinPBX : : release ( struct join_relation * relation , int location , int cause )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * reltemp , * * relationpointer ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-07-17 17:28:09 +00:00
class Join * join ;
2007-07-15 10:01:27 +00:00
int destroy = 0 ;
2007-05-06 13:54:52 +00:00
2007-05-15 20:59:29 +00:00
/* remove from bridge */
2009-07-05 20:14:21 +00:00
if ( relation - > channel_state ! = 0 ) {
2008-05-25 14:12:20 +00:00
relation - > channel_state = 0 ;
2010-01-16 10:20:23 +00:00
trigger_work ( & j_updatebridge ) ;
2007-07-17 17:28:09 +00:00
// note: if join is not released, bridge must be updated
2007-05-06 13:54:52 +00:00
}
/* detach given interface */
2007-07-26 12:23:56 +00:00
reltemp = j_relation ;
relationpointer = & j_relation ;
2009-07-05 20:14:21 +00:00
while ( reltemp ) {
2007-05-06 13:54:52 +00:00
/* endpoint of function call */
2007-07-15 10:01:27 +00:00
if ( relation = = reltemp )
break ;
relationpointer = & reltemp - > next ;
reltemp = reltemp - > next ;
2007-05-06 13:54:52 +00:00
}
2007-07-15 10:01:27 +00:00
if ( ! reltemp )
FATAL ( " relation not in list of our relations. this must not happen. \n " ) ;
2007-07-29 09:17:29 +00:00
//printf("releasing relation %d\n", reltemp->epoint_id);
2007-07-15 10:01:27 +00:00
* relationpointer = reltemp - > next ;
2007-07-17 17:28:09 +00:00
FREE ( reltemp , sizeof ( struct join_relation ) ) ;
2007-07-15 10:01:27 +00:00
cmemuse - - ;
relation = reltemp = NULL ; // just in case of reuse fault;
2007-05-06 13:54:52 +00:00
/* if no more relation */
2009-07-05 20:14:21 +00:00
if ( ! j_relation ) {
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " join is completely removed. \n " ) ;
/* there is no more endpoint related to the join */
2007-07-15 10:01:27 +00:00
destroy = 1 ;
2007-05-06 13:54:52 +00:00
delete this ;
2007-07-17 17:28:09 +00:00
// end of join object!
PDEBUG ( DEBUG_JOIN , " join completely removed! \n " ) ;
2007-05-06 13:54:52 +00:00
} else
2007-07-17 17:28:09 +00:00
/* if join is a party line */
2009-07-05 20:14:21 +00:00
if ( j_partyline ) {
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " join is a conference room, so we keep it alive until the last party left. \n " ) ;
2007-05-06 13:54:52 +00:00
} else
/* if only one relation left */
2009-07-05 20:14:21 +00:00
if ( ! j_relation - > next ) {
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " join has one relation left, so we send it a release with the given cause %d. \n " , cause ) ;
2007-07-26 12:23:56 +00:00
message = message_create ( j_serial , j_relation - > epoint_id , JOIN_TO_EPOINT , MESSAGE_RELEASE ) ;
2007-05-06 13:54:52 +00:00
message - > param . disconnectinfo . cause = cause ;
message - > param . disconnectinfo . location = location ;
message_put ( message ) ;
2007-07-15 10:01:27 +00:00
destroy = 1 ;
2007-05-06 13:54:52 +00:00
delete this ;
2007-07-17 17:28:09 +00:00
// end of join object!
PDEBUG ( DEBUG_JOIN , " join completely removed! \n " ) ;
2007-05-06 13:54:52 +00:00
}
2007-07-17 17:28:09 +00:00
join = join_first ;
2009-07-05 20:14:21 +00:00
while ( join ) {
2007-07-26 12:23:56 +00:00
if ( options . deb & DEBUG_JOIN & & join - > j_type = = JOIN_TYPE_PBX )
2007-07-17 17:28:09 +00:00
joinpbx_debug ( ( class JoinPBX * ) join , " join_release{all joins left} " ) ;
join = join - > next ;
2007-05-06 13:54:52 +00:00
}
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " join_release(): ended. \n " ) ;
2007-07-15 10:01:27 +00:00
return ( destroy ) ;
2007-05-06 13:54:52 +00:00
}
2007-07-17 17:28:09 +00:00
/* count number of relations in a join
2007-05-06 13:54:52 +00:00
*/
2008-06-14 06:34:50 +00:00
int joinpbx_countrelations ( unsigned int join_id )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation ;
2007-05-06 13:54:52 +00:00
int i ;
2007-07-17 17:28:09 +00:00
class Join * join ;
class JoinPBX * joinpbx ;
2007-05-06 13:54:52 +00:00
2007-07-17 17:28:09 +00:00
join = find_join_id ( join_id ) ;
2007-05-06 13:54:52 +00:00
2007-07-17 17:28:09 +00:00
if ( ! join )
2007-05-06 13:54:52 +00:00
return ( 0 ) ;
2007-07-26 12:23:56 +00:00
if ( join - > j_type ! = JOIN_TYPE_PBX )
2007-05-06 13:54:52 +00:00
return ( 0 ) ;
2007-07-17 17:28:09 +00:00
joinpbx = ( class JoinPBX * ) join ;
2007-05-06 13:54:52 +00:00
i = 0 ;
2007-07-26 12:23:56 +00:00
relation = joinpbx - > j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-05-06 13:54:52 +00:00
i + + ;
relation = relation - > next ;
}
return ( i ) ;
}
2009-09-06 19:49:53 +00:00
/* check if one is calling and all other relations are setup-realations */
int joinpbx_onecalling_othersetup ( struct join_relation * relation )
{
int calling = 0 , other = 0 ;
while ( relation ) {
switch ( relation - > type ) {
case RELATION_TYPE_CALLING :
calling + + ;
break ;
case RELATION_TYPE_SETUP :
break ;
default :
other + + ;
break ;
}
relation = relation - > next ;
}
if ( calling = = 1 & & other = = 0 )
return ( 1 ) ;
return ( 0 ) ;
}
2007-07-17 17:28:09 +00:00
void JoinPBX : : remove_relation ( struct join_relation * relation )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * temp , * * tempp ;
2007-05-06 13:54:52 +00:00
if ( ! relation )
return ;
2007-07-26 12:23:56 +00:00
temp = j_relation ;
tempp = & j_relation ;
2009-07-05 20:14:21 +00:00
while ( temp ) {
2007-05-06 13:54:52 +00:00
if ( temp = = relation )
break ;
tempp = & temp - > next ;
temp = temp - > next ;
}
2009-07-05 20:14:21 +00:00
if ( ! temp ) {
2007-07-17 17:28:09 +00:00
PERROR ( " relation not in join. \n " ) ;
2007-05-06 13:54:52 +00:00
return ;
}
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " removing relation. \n " ) ;
2007-05-06 13:54:52 +00:00
* tempp = relation - > next ;
2007-07-17 17:28:09 +00:00
FREE ( temp , sizeof ( struct join_relation ) ) ;
2007-05-06 13:54:52 +00:00
cmemuse - - ;
}
2007-07-17 17:28:09 +00:00
struct join_relation * JoinPBX : : add_relation ( void )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation ;
2007-05-06 13:54:52 +00:00
2009-07-05 20:14:21 +00:00
if ( ! j_relation ) {
2007-07-17 17:28:09 +00:00
PERROR ( " there is no first relation to this join \n " ) ;
2007-05-06 13:54:52 +00:00
return ( NULL ) ;
}
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2007-05-06 13:54:52 +00:00
while ( relation - > next )
relation = relation - > next ;
2007-07-17 17:28:09 +00:00
relation - > next = ( struct join_relation * ) MALLOC ( sizeof ( struct join_relation ) ) ;
2007-05-06 13:54:52 +00:00
cmemuse + + ;
/* the record pointer is set at the first time the data is received for the relation */
2007-07-17 17:28:09 +00:00
// if (options.deb & DEBUG_JOIN)
// joinpbx_debug(join, "add_relation");
2007-05-06 13:54:52 +00:00
return ( relation - > next ) ;
}
2007-07-17 17:28:09 +00:00
/* epoint sends a message to a join
2007-05-06 13:54:52 +00:00
*
*/
2008-06-14 06:34:50 +00:00
void JoinPBX : : message_epoint ( unsigned int epoint_id , int message_type , union parameter * param )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
class Join * cl ;
struct join_relation * relation , * reltemp ;
2007-05-06 13:54:52 +00:00
int num ;
int new_state ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
// int size, writesize, oldpointer;
2007-07-07 15:13:20 +00:00
char * number , * numbers ;
2007-05-06 13:54:52 +00:00
2009-07-05 20:14:21 +00:00
if ( ! epoint_id ) {
2007-05-06 13:54:52 +00:00
PERROR ( " software error, epoint == NULL \n " ) ;
return ;
}
2009-07-05 20:14:21 +00:00
// if (options.deb & DEBUG_JOIN) {
2007-07-17 17:28:09 +00:00
// PDEBUG(DEBUG_JOIN, "message %d received from ep%d.\n", message, epoint->ep_serial);
// joinpbx_debug(join,"Join::message_epoint");
2007-05-06 13:54:52 +00:00
// }
2009-07-05 20:14:21 +00:00
if ( options . deb & DEBUG_JOIN ) {
2012-01-14 17:36:26 +00:00
if ( message_type ) {
2007-07-17 17:28:09 +00:00
cl = join_first ;
2009-07-05 20:14:21 +00:00
while ( cl ) {
2007-07-26 12:23:56 +00:00
if ( cl - > j_type = = JOIN_TYPE_PBX )
2007-07-17 17:28:09 +00:00
joinpbx_debug ( ( class JoinPBX * ) cl , " Join::message_epoint{all joins before processing} " ) ;
2007-05-06 13:54:52 +00:00
cl = cl - > next ;
}
}
}
/* check relation */
2007-07-26 12:23:56 +00:00
relation = j_relation ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-05-06 13:54:52 +00:00
if ( relation - > epoint_id = = epoint_id )
break ;
relation = relation - > next ;
}
2009-07-05 20:14:21 +00:00
if ( ! relation ) {
2007-07-26 12:23:56 +00:00
PDEBUG ( DEBUG_JOIN , " no relation back to the endpoint found, ignoring (join=%d, endpoint=%d) \n " , j_serial , epoint_id ) ;
2007-05-06 13:54:52 +00:00
return ;
}
2009-09-06 13:36:36 +00:00
/* count relations */
num = joinpbx_countrelations ( j_serial ) ;
2007-08-24 06:39:42 +00:00
/* process party line */
2009-07-05 20:14:21 +00:00
if ( message_type = = MESSAGE_SETUP ) if ( param - > setup . partyline & & ! j_partyline ) {
2007-08-24 06:39:42 +00:00
j_partyline = param - > setup . partyline ;
2007-09-10 05:10:50 +00:00
j_partyline_jingle = param - > setup . partyline_jingle ;
2007-08-24 06:39:42 +00:00
}
2009-07-05 20:14:21 +00:00
if ( j_partyline ) {
switch ( message_type ) {
2007-08-24 06:39:42 +00:00
case MESSAGE_SETUP :
PDEBUG ( DEBUG_JOIN , " respsone with connect in partyline mode. \n " ) ;
relation - > type = RELATION_TYPE_CONNECT ;
message = message_create ( j_serial , epoint_id , JOIN_TO_EPOINT , MESSAGE_CONNECT ) ;
SPRINT ( message - > param . connectinfo . id , " %d " , j_partyline ) ;
message - > param . connectinfo . ntype = INFO_NTYPE_UNKNOWN ;
message_put ( message ) ;
2010-01-16 10:20:23 +00:00
trigger_work ( & j_updatebridge ) ;
2007-09-22 07:28:26 +00:00
if ( j_partyline_jingle )
2007-09-10 05:10:50 +00:00
play_jingle ( 1 ) ;
2007-08-24 06:39:42 +00:00
break ;
case MESSAGE_AUDIOPATH :
PDEBUG ( DEBUG_JOIN , " join received channel message: %d. \n " , param - > audiopath ) ;
2009-07-05 20:14:21 +00:00
if ( relation - > channel_state ! = param - > audiopath ) {
2007-08-24 06:39:42 +00:00
relation - > channel_state = param - > audiopath ;
2010-01-16 10:20:23 +00:00
trigger_work ( & j_updatebridge ) ;
2007-08-24 06:39:42 +00:00
if ( options . deb & DEBUG_JOIN )
joinpbx_debug ( this , " Join::message_epoint{after setting new channel state} " ) ;
}
break ;
2012-08-21 07:44:33 +00:00
/* track notify */
case MESSAGE_NOTIFY :
switch ( param - > notifyinfo . notify ) {
case INFO_NOTIFY_USER_SUSPENDED :
case INFO_NOTIFY_USER_RESUMED :
case INFO_NOTIFY_REMOTE_HOLD :
case INFO_NOTIFY_REMOTE_RETRIEVAL :
case INFO_NOTIFY_CONFERENCE_ESTABLISHED :
case INFO_NOTIFY_CONFERENCE_DISCONNECTED :
new_state = track_notify ( relation - > rx_state , param - > notifyinfo . notify ) ;
if ( new_state ! = relation - > rx_state ) {
relation - > rx_state = new_state ;
trigger_work ( & j_updatebridge ) ;
if ( options . deb & DEBUG_JOIN )
joinpbx_debug ( this , " Join::message_epoint{after setting new rx state} " ) ;
}
break ;
}
break ;
2007-08-24 06:39:42 +00:00
case MESSAGE_DISCONNECT :
PDEBUG ( DEBUG_JOIN , " releasing after receiving disconnect, because join in partyline mode. \n " ) ;
message = message_create ( j_serial , epoint_id , JOIN_TO_EPOINT , MESSAGE_RELEASE ) ;
message - > param . disconnectinfo . cause = CAUSE_NORMAL ;
message - > param . disconnectinfo . location = LOCATION_PRIVATE_LOCAL ;
message_put ( message ) ;
// fall through
case MESSAGE_RELEASE :
PDEBUG ( DEBUG_JOIN , " releasing from join \n " ) ;
release ( relation , 0 , 0 ) ;
2008-05-12 16:35:48 +00:00
if ( j_partyline_jingle )
2007-09-10 05:10:50 +00:00
play_jingle ( 0 ) ;
2007-08-24 06:39:42 +00:00
break ;
default :
PDEBUG ( DEBUG_JOIN , " ignoring message, because join in partyline mode. \n " ) ;
}
return ;
}
/* process messages */
2009-07-05 20:14:21 +00:00
switch ( message_type ) {
2007-07-26 12:23:56 +00:00
/* process audio path message */
case MESSAGE_AUDIOPATH :
2012-01-19 08:14:58 +00:00
PDEBUG ( DEBUG_JOIN , " join received channel message: audiopath=%d, current relation's channel_state=%d \n " , param - > audiopath , relation - > channel_state ) ;
2009-07-05 20:14:21 +00:00
if ( relation - > channel_state ! = param - > audiopath ) {
2007-07-26 12:23:56 +00:00
relation - > channel_state = param - > audiopath ;
2010-01-16 10:20:23 +00:00
trigger_work ( & j_updatebridge ) ;
2007-07-17 17:28:09 +00:00
if ( options . deb & DEBUG_JOIN )
joinpbx_debug ( this , " Join::message_epoint{after setting new channel state} " ) ;
2007-05-06 13:54:52 +00:00
}
return ;
2012-12-23 05:45:43 +00:00
case MESSAGE_UPDATEBRIDGE :
trigger_work ( & j_updatebridge ) ;
joinpbx_debug ( this , " Join::message_epoint{bridge is updated due to request from mISDN port} " ) ;
break ;
2007-05-06 13:54:52 +00:00
/* track notify */
case MESSAGE_NOTIFY :
2009-07-05 20:14:21 +00:00
switch ( param - > notifyinfo . notify ) {
2007-05-06 13:54:52 +00:00
case INFO_NOTIFY_USER_SUSPENDED :
case INFO_NOTIFY_USER_RESUMED :
case INFO_NOTIFY_REMOTE_HOLD :
case INFO_NOTIFY_REMOTE_RETRIEVAL :
case INFO_NOTIFY_CONFERENCE_ESTABLISHED :
case INFO_NOTIFY_CONFERENCE_DISCONNECTED :
new_state = track_notify ( relation - > rx_state , param - > notifyinfo . notify ) ;
2009-07-05 20:14:21 +00:00
if ( new_state ! = relation - > rx_state ) {
2007-05-06 13:54:52 +00:00
relation - > rx_state = new_state ;
2010-01-16 10:20:23 +00:00
trigger_work ( & j_updatebridge ) ;
2007-07-17 17:28:09 +00:00
if ( options . deb & DEBUG_JOIN )
joinpbx_debug ( this , " Join::message_epoint{after setting new rx state} " ) ;
2007-05-06 13:54:52 +00:00
}
break ;
default :
/* send notification to all other endpoints */
2007-07-26 12:23:56 +00:00
reltemp = j_relation ;
2009-07-05 20:14:21 +00:00
while ( reltemp ) {
if ( reltemp - > epoint_id ! = epoint_id & & reltemp - > epoint_id ) {
2007-07-26 12:23:56 +00:00
message = message_create ( j_serial , reltemp - > epoint_id , JOIN_TO_EPOINT , MESSAGE_NOTIFY ) ;
2007-05-06 13:54:52 +00:00
memcpy ( & message - > param , param , sizeof ( union parameter ) ) ;
message_put ( message ) ;
}
2007-07-15 10:01:27 +00:00
reltemp = reltemp - > next ;
2007-05-06 13:54:52 +00:00
}
}
return ;
2007-07-15 10:01:27 +00:00
/* relations sends a connect */
case MESSAGE_CONNECT :
/* outgoing setup type becomes connected */
if ( relation - > type = = RELATION_TYPE_SETUP )
relation - > type = RELATION_TYPE_CONNECT ;
/* release other relations in setup state */
release_again :
2007-07-29 09:17:29 +00:00
reltemp = j_relation ;
2009-07-05 20:14:21 +00:00
while ( reltemp ) {
2007-07-29 09:17:29 +00:00
//printf("connect, checking relation %d\n", reltemp->epoint_id);
2009-07-05 20:14:21 +00:00
if ( reltemp - > type = = RELATION_TYPE_SETUP ) {
2007-07-29 09:17:29 +00:00
//printf("relation %d is of type setup, releasing\n", reltemp->epoint_id);
/* send release to endpoint */
message = message_create ( j_serial , reltemp - > epoint_id , JOIN_TO_EPOINT , MESSAGE_RELEASE ) ;
message - > param . disconnectinfo . cause = CAUSE_NONSELECTED ;
message - > param . disconnectinfo . location = LOCATION_PRIVATE_LOCAL ;
message_put ( message ) ;
if ( release ( reltemp , LOCATION_PRIVATE_LOCAL , CAUSE_NORMAL ) ) // dummy cause, should not be used, since calling and connected endpoint still exist afterwards.
2007-07-17 17:28:09 +00:00
return ; // must return, because join IS destroyed
2007-07-15 10:01:27 +00:00
goto release_again ;
}
2007-07-29 09:17:29 +00:00
if ( reltemp - > type = = RELATION_TYPE_CALLING )
reltemp - > type = RELATION_TYPE_CONNECT ;
reltemp = reltemp - > next ;
2007-07-15 10:01:27 +00:00
}
break ; // continue with our message
/* release is sent by endpoint */
case MESSAGE_RELEASE :
2009-07-05 20:14:21 +00:00
switch ( relation - > type ) {
2007-07-29 09:17:29 +00:00
case RELATION_TYPE_SETUP : /* by called */
2007-07-15 10:01:27 +00:00
/* collect cause and send collected cause */
2007-07-26 12:23:56 +00:00
collect_cause ( & j_multicause , & j_multilocation , param - > disconnectinfo . cause , param - > disconnectinfo . location ) ;
2007-07-31 05:34:18 +00:00
if ( j_multicause )
release ( relation , j_multilocation , j_multicause ) ;
else
release ( relation , LOCATION_PRIVATE_LOCAL , CAUSE_UNSPECIFIED ) ;
2007-07-29 09:17:29 +00:00
break ;
case RELATION_TYPE_CALLING : /* by calling */
2007-09-15 08:40:29 +00:00
/* remove us, if we don't have a called releation yet */
2009-07-05 20:14:21 +00:00
if ( ! j_relation - > next ) {
2007-09-15 08:40:29 +00:00
release ( j_relation , LOCATION_PRIVATE_LOCAL , CAUSE_NORMAL ) ;
return ; // must return, because join IS destroyed
}
2009-09-06 13:36:36 +00:00
/* in a conf, we don't kill the other members */
2009-09-06 19:49:53 +00:00
if ( num > 2 & & ! joinpbx_onecalling_othersetup ( j_relation ) ) {
2009-09-06 13:36:36 +00:00
release ( relation , 0 , 0 ) ;
return ;
}
/* remove all relations that are of called type */
2007-07-29 09:17:29 +00:00
release_again2 :
reltemp = j_relation ;
2009-07-05 20:14:21 +00:00
while ( reltemp ) {
if ( reltemp - > type = = RELATION_TYPE_SETUP ) {
2007-07-29 09:17:29 +00:00
/* send release to endpoint */
message = message_create ( j_serial , reltemp - > epoint_id , JOIN_TO_EPOINT , message_type ) ;
memcpy ( & message - > param , param , sizeof ( union parameter ) ) ;
message_put ( message ) ;
if ( release ( reltemp , LOCATION_PRIVATE_LOCAL , CAUSE_NORMAL ) )
return ; // must return, because join IS destroyed
goto release_again2 ;
}
reltemp = reltemp - > next ;
}
PERROR ( " we are still here, this should not happen \n " ) ;
break ;
default : /* by connected */
2007-07-15 10:01:27 +00:00
/* send current cause */
release ( relation , param - > disconnectinfo . location , param - > disconnectinfo . cause ) ;
}
2007-07-17 17:28:09 +00:00
return ; // must return, because join may be destroyed
2007-05-06 13:54:52 +00:00
}
/* check number of relations */
2009-09-06 19:49:53 +00:00
if ( num > 2 & & ! joinpbx_onecalling_othersetup ( j_relation ) & & message_type ! = MESSAGE_CONNECT ) {
PDEBUG ( DEBUG_JOIN , " we are in a conference, so we ignore the messages, except MESSAGE_CONNECT. \n " ) ;
2007-05-06 13:54:52 +00:00
return ;
}
2009-09-06 19:49:53 +00:00
/* if join has no other relation, we process the setup message */
if ( num = = 1 ) {
2009-07-05 20:14:21 +00:00
switch ( message_type ) {
2007-05-06 13:54:52 +00:00
case MESSAGE_SETUP :
2009-07-05 20:14:21 +00:00
if ( param - > setup . dialinginfo . itype = = INFO_ITYPE_ISDN_EXTENSION ) {
2009-12-25 13:38:42 +00:00
/* in case of keypad */
numbers = param - > setup . dialinginfo . keypad ;
if ( numbers [ 0 ] ) {
while ( ( number = strsep ( & numbers , " , " ) ) ) {
if ( out_setup ( epoint_id , message_type , param , NULL , number ) )
return ; // join destroyed
}
/* after keypad finish dialing */
break ;
2009-10-27 07:02:16 +00:00
}
2009-12-25 13:38:42 +00:00
/* dialed number */
2009-10-27 07:02:16 +00:00
numbers = param - > setup . dialinginfo . id ;
while ( ( number = strsep ( & numbers , " , " ) ) ) {
2009-12-25 13:38:42 +00:00
if ( out_setup ( epoint_id , message_type , param , number , NULL ) )
2007-07-17 17:28:09 +00:00
return ; // join destroyed
2007-05-06 13:54:52 +00:00
}
break ;
}
2009-12-25 13:53:09 +00:00
if ( out_setup ( epoint_id , message_type , param , param - > setup . dialinginfo . id , param - > setup . dialinginfo . keypad ) )
2007-07-17 17:28:09 +00:00
return ; // join destroyed
2007-05-06 13:54:52 +00:00
break ;
default :
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " no need to send a message because there is no other endpoint than the calling one. \n " ) ;
2007-05-06 13:54:52 +00:00
}
2009-07-05 20:14:21 +00:00
} else {
2009-09-06 19:49:53 +00:00
/* sending message to other relation(s) */
relation = j_relation ;
while ( relation ) {
if ( relation - > epoint_id ! = epoint_id ) {
PDEBUG ( DEBUG_JOIN , " sending message ep%ld -> ep%ld. \n " , epoint_id , relation - > epoint_id ) ;
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , message_type ) ;
memcpy ( & message - > param , param , sizeof ( union parameter ) ) ;
message_put ( message ) ;
PDEBUG ( DEBUG_JOIN , " message sent. \n " ) ;
}
relation = relation - > next ;
}
2007-05-06 13:54:52 +00:00
}
}
int track_notify ( int oldstate , int notify )
{
int newstate = oldstate ;
2009-07-05 20:14:21 +00:00
switch ( notify ) {
2007-05-06 13:54:52 +00:00
case INFO_NOTIFY_USER_RESUMED :
case INFO_NOTIFY_REMOTE_RETRIEVAL :
case INFO_NOTIFY_CONFERENCE_DISCONNECTED :
case INFO_NOTIFY_RESERVED_CT_1 :
case INFO_NOTIFY_RESERVED_CT_2 :
case INFO_NOTIFY_CALL_IS_DIVERTING :
newstate = NOTIFY_STATE_ACTIVE ;
break ;
case INFO_NOTIFY_USER_SUSPENDED :
newstate = NOTIFY_STATE_SUSPEND ;
break ;
case INFO_NOTIFY_REMOTE_HOLD :
newstate = NOTIFY_STATE_HOLD ;
break ;
case INFO_NOTIFY_CONFERENCE_ESTABLISHED :
newstate = NOTIFY_STATE_CONFERENCE ;
break ;
}
return ( newstate ) ;
}
/*
* setup to exactly one endpoint
* if it fails , the calling endpoint is released .
* if other outgoing endpoints already exists , they are release as well .
2007-07-17 17:28:09 +00:00
* note : if this functions fails , it will destroy its own join object !
2007-05-06 13:54:52 +00:00
*/
2009-10-27 07:02:16 +00:00
int JoinPBX : : out_setup ( unsigned int epoint_id , int message_type , union parameter * param , char * newnumber , char * newkeypad )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
struct join_relation * relation ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
class Endpoint * epoint ;
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_JOIN , " no endpoint found, so we will create an endpoint and send the setup message we have. \n " ) ;
2007-05-06 13:54:52 +00:00
/* create a new relation */
if ( ! ( relation = add_relation ( ) ) )
2007-07-15 10:01:27 +00:00
FATAL ( " No memory for relation. \n " ) ;
2007-05-06 13:54:52 +00:00
relation - > type = RELATION_TYPE_SETUP ;
2008-05-25 14:12:20 +00:00
relation - > channel_state = 0 ; /* audio is assumed on a new join */
2007-07-17 17:28:09 +00:00
relation - > tx_state = NOTIFY_STATE_ACTIVE ; /* new joins always assumed to be active */
relation - > rx_state = NOTIFY_STATE_ACTIVE ; /* new joins always assumed to be active */
2007-05-06 13:54:52 +00:00
/* create a new endpoint */
2007-08-11 13:57:58 +00:00
epoint = new Endpoint ( 0 , j_serial ) ;
2007-05-06 13:54:52 +00:00
if ( ! epoint )
2007-07-15 10:01:27 +00:00
FATAL ( " No memory for Endpoint instance \n " ) ;
2012-01-16 08:14:22 +00:00
epoint - > ep_app = new_endpointapp ( epoint , 1 , EAPP_TYPE_PBX ) ; // outgoing
2007-05-06 13:54:52 +00:00
relation - > epoint_id = epoint - > ep_serial ;
/* send setup message to new endpoint */
2007-07-26 12:23:56 +00:00
//printf("JOLLY DEBUG: %d\n",join_countrelations(j_serial));
2007-07-17 17:28:09 +00:00
//i if (options.deb & DEBUG_JOIN)
// joinpbx_debug(join, "Join::message_epoint");
2007-07-26 12:23:56 +00:00
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , message_type ) ;
2007-05-06 13:54:52 +00:00
memcpy ( & message - > param , param , sizeof ( union parameter ) ) ;
if ( newnumber )
2007-07-07 15:13:20 +00:00
SCPY ( message - > param . setup . dialinginfo . id , newnumber ) ;
2009-12-25 13:38:42 +00:00
else
message - > param . setup . dialinginfo . id [ 0 ] = ' \0 ' ;
2009-10-27 07:02:16 +00:00
if ( newkeypad )
SCPY ( message - > param . setup . dialinginfo . keypad , newkeypad ) ;
2009-12-25 13:38:42 +00:00
else
message - > param . setup . dialinginfo . keypad [ 0 ] = ' \0 ' ;
2009-10-27 07:02:16 +00:00
PDEBUG ( DEBUG_JOIN , " setup message sent to ep %d with number='%s' keypad='%s'. \n " , relation - > epoint_id , message - > param . setup . dialinginfo . id , message - > param . setup . dialinginfo . keypad ) ;
2007-05-06 13:54:52 +00:00
message_put ( message ) ;
return ( 0 ) ;
}
2007-07-15 10:01:27 +00:00
2007-09-10 05:10:50 +00:00
/* send play message to all members to play join/release jingle */
void JoinPBX : : play_jingle ( int in )
{
struct join_relation * relation ;
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-09-10 05:10:50 +00:00
relation = j_relation ;
2007-10-01 07:54:51 +00:00
if ( ! relation )
return ;
if ( ! relation - > next )
return ;
2009-07-05 20:14:21 +00:00
while ( relation ) {
2007-09-10 05:10:50 +00:00
message = message_create ( j_serial , relation - > epoint_id , JOIN_TO_EPOINT , MESSAGE_TONE ) ;
2008-05-12 16:35:48 +00:00
SCPY ( message - > param . tone . name , ( char * ) ( ( in ) ? " joined " : " left " ) ) ;
2007-09-10 05:10:50 +00:00
message_put ( message ) ;
relation = relation - > next ;
}
}