@ -82,6 +82,7 @@ clear_con_cb on_connection_cleared;
answer_call_cb on_answer_call ;
progress_cb on_progress ;
rfc2833_cb on_set_rfc2833_payload ;
hangup_cb on_hangup ;
/* global debug flag */
int h323debug ;
@ -137,6 +138,9 @@ struct oh323_pvt {
struct ast_rtp * rtp ; /* RTP Session */
int dtmfmode ; /* What DTMF Mode is being used */
struct ast_dsp * vad ; /* Used for in-band DTMF detection */
int nativeformats ; /* Codec formats supported by a channel */
int needhangup ; /* Send hangup when Asterisk is ready */
int hangupcause ; /* Hangup cause from OpenH323 layer */
struct oh323_pvt * next ; /* Next channel in list */
} * iflist = NULL ;
@ -213,6 +217,61 @@ static const struct ast_channel_tech oh323_tech = {
# endif
} ;
static void oh323_update_info ( struct ast_channel * c )
{
struct oh323_pvt * pvt = c - > tech_pvt ;
ast_mutex_lock ( & pvt - > lock ) ;
if ( c - > nativeformats ! = pvt - > nativeformats ) {
if ( h323debug )
ast_log ( LOG_DEBUG , " Preparing %s for new native format \n " , c - > name ) ;
c - > nativeformats = pvt - > nativeformats ;
ast_set_read_format ( c , c - > readformat ) ;
ast_set_write_format ( c , c - > writeformat ) ;
}
if ( pvt - > needhangup ) {
if ( h323debug )
ast_log ( LOG_DEBUG , " Process pending hangup for %s \n " , c - > name ) ;
c - > _softhangup | = AST_SOFTHANGUP_DEV ;
c - > hangupcause = pvt - > hangupcause ;
ast_queue_hangup ( c ) ;
pvt - > needhangup = 0 ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
}
static void cleanup_call_details ( call_details_t * cd )
{
if ( cd - > call_token ) {
free ( cd - > call_token ) ;
cd - > call_token = NULL ;
}
if ( cd - > call_source_aliases ) {
free ( cd - > call_source_aliases ) ;
cd - > call_source_aliases = NULL ;
}
if ( cd - > call_dest_alias ) {
free ( cd - > call_dest_alias ) ;
cd - > call_dest_alias = NULL ;
}
if ( cd - > call_source_name ) {
free ( cd - > call_source_name ) ;
cd - > call_source_name = NULL ;
}
if ( cd - > call_source_e164 ) {
free ( cd - > call_source_e164 ) ;
cd - > call_source_e164 = NULL ;
}
if ( cd - > call_dest_e164 ) {
free ( cd - > call_dest_e164 ) ;
cd - > call_dest_e164 = NULL ;
}
if ( cd - > sourceIp ) {
free ( cd - > sourceIp ) ;
cd - > sourceIp = NULL ;
}
}
static void __oh323_destroy ( struct oh323_pvt * p )
{
struct oh323_pvt * cur , * prev = NULL ;
@ -221,6 +280,12 @@ static void __oh323_destroy(struct oh323_pvt *p)
ast_rtp_destroy ( p - > rtp ) ;
}
/* Free dsp used for in-band DTMF detection */
if ( p - > vad ) {
ast_dsp_free ( p - > vad ) ;
}
cleanup_call_details ( & p - > cd ) ;
/* Unlink us from the owner if we have one */
if ( p - > owner ) {
ast_mutex_lock ( & p - > owner - > lock ) ;
@ -494,13 +559,20 @@ static struct oh323_peer *build_peer(char *name, struct ast_variable *v)
static int oh323_digit ( struct ast_channel * c , char digit )
{
struct oh323_pvt * p = ( struct oh323_pvt * ) c - > tech_pvt ;
if ( p & & p - > rtp & & ( p - > dtmfmode & H323_DTMF_RFC2833 ) ) {
if ( h323debug )
ast_log ( LOG_DEBUG , " Sending digit %c on %s \n " , digit , c - > name ) ;
if ( ! p )
return - 1 ;
ast_mutex_lock ( & p - > lock ) ;
if ( p - > rtp & & ( p - > dtmfmode & H323_DTMF_RFC2833 ) ) {
ast_rtp_senddigit ( p - > rtp , digit ) ;
}
/* If in-band DTMF is desired, send that */
if ( p & & ( p - > dtmfmode & H323_DTMF_INBAND ) ) {
if ( ( p - > dtmfmode & H323_DTMF_INBAND ) ) {
h323_send_tone ( p - > cd . call_token , digit ) ;
}
ast_mutex_unlock ( & p - > lock ) ;
oh323_update_info ( c ) ;
return 0 ;
}
@ -516,19 +588,31 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
char addr [ INET_ADDRSTRLEN ] ;
char called_addr [ 1024 ] ;
if ( ( c - > _state ! = AST_STATE_DOWN ) & & ( c - > _state ! = AST_STATE_RESERVED ) ) {
if ( h323debug ) {
ast_log ( LOG_DEBUG , " Calling to %s on %s \n " , dest , c - > name ) ;
}
if ( ( c - > _state ! = AST_STATE_DOWN ) & & ( c - > _state ! = AST_STATE_RESERVED ) ) {
ast_log ( LOG_WARNING , " Line is already in use (%s) \n " , c - > name ) ;
return - 1 ;
}
/* Clear and then set the address to call */
memset ( addr , 0 , sizeof ( addr ) ) ;
if ( usingGk ) {
memcpy ( addr , dest , strlen ( addr ) ) ;
pvt - > options . port = h323_signalling_port ;
if ( ast_strlen_zero ( pvt - > exten ) ) {
strncpy ( called_addr , dest , sizeof ( called_addr ) ) ;
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s " , pvt - > exten , dest ) ;
}
} else {
ast_inet_ntoa ( addr , sizeof ( addr ) , pvt - > sa . sin_addr ) ;
pvt - > options . port = htons ( pvt - > sa . sin_port ) ;
if ( ast_strlen_zero ( pvt - > exten ) ) {
snprintf ( called_addr , sizeof ( called_addr ) , " %s:%d " , addr , pvt - > options . port ) ;
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s:%d " , pvt - > exten , addr , pvt - > options . port ) ;
}
}
/* make sure null terminated */
called_addr [ sizeof ( called_addr ) - 1 ] = ' \0 ' ;
if ( c - > cid . cid_num ) {
strncpy ( pvt - > options . cid_num , c - > cid . cid_num , sizeof ( pvt - > options . cid_num ) ) ;
@ -540,17 +624,13 @@ static int oh323_call(struct ast_channel *c, char *dest, int timeout)
/* indicate that this is an outgoing call */
pvt - > outgoing = 1 ;
if ( pvt - > exten ) {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s:%d " , pvt - > exten , addr , pvt - > options . port ) ;
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s:%d " , addr , pvt - > options . port ) ;
}
ast_log ( LOG_DEBUG , " Placing outgoing call to %s, %d \n " , called_addr , pvt - > options . dtmfcodec ) ;
res = h323_make_call ( called_addr , & ( pvt - > cd ) , & pvt - > options ) ;
if ( res ) {
ast_log ( LOG_NOTICE , " h323_make_call failed(%s) \n " , c - > name ) ;
return - 1 ;
}
oh323_update_info ( c ) ;
return 0 ;
}
@ -558,9 +638,19 @@ static int oh323_answer(struct ast_channel *c)
{
int res ;
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
char * token ;
res = h323_answering_call ( pvt - > cd . call_token , 0 ) ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Answering on %s \n " , c - > name ) ;
ast_mutex_lock ( & pvt - > lock ) ;
token = pvt - > cd . call_token ? strdup ( pvt - > cd . call_token ) : NULL ;
ast_mutex_unlock ( & pvt - > lock ) ;
res = h323_answering_call ( token , 0 ) ;
if ( token )
free ( token ) ;
oh323_update_info ( c ) ;
if ( c - > _state ! = AST_STATE_UP ) {
ast_setstate ( c , AST_STATE_UP ) ;
}
@ -572,6 +662,11 @@ static int oh323_hangup(struct ast_channel *c)
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
int needcancel = 0 ;
int q931cause = AST_CAUSE_NORMAL_CLEARING ;
char * call_token ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Hanging up call %s \n " , c - > name ) ;
if ( ! c - > tech_pvt ) {
ast_log ( LOG_DEBUG , " Asked to hangup channel not connected \n " ) ;
@ -587,12 +682,7 @@ static int oh323_hangup(struct ast_channel *c)
if ( ! c | | ( c - > _state ! = AST_STATE_UP ) ) {
needcancel = 1 ;
}
pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
/* Free dsp used for in-band DTMF detection */
if ( pvt - > vad ) {
ast_dsp_free ( pvt - > vad ) ;
}
pvt - > owner = NULL ;
c - > tech_pvt = NULL ;
@ -616,12 +706,19 @@ static int oh323_hangup(struct ast_channel *c)
}
/* Start the process if it's not already started */
if ( ! pvt - > alreadygone ) {
if ( h323_clear_call ( ( pvt - > cd ) . call_token , q931cause ) ) {
ast_log ( LOG_DEBUG , " ClearCall failed. \n " ) ;
if ( ! pvt - > alreadygone & & ! pvt - > hangupcause ) {
call_token = pvt - > cd . call_token ? strdup ( pvt - > cd . call_token ) : NULL ;
if ( call_token ) {
/* Release lock to eliminate deadlock */
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323_clear_call ( call_token , q931cause ) ) {
ast_log ( LOG_DEBUG , " ClearCall failed. \n " ) ;
}
free ( call_token ) ;
ast_mutex_lock ( & pvt - > lock ) ;
}
pvt - > needdestroy = 1 ;
}
pvt - > needdestroy = 1 ;
/* Update usage counter */
ast_mutex_lock ( & usecnt_lock ) ;
@ -630,8 +727,8 @@ static int oh323_hangup(struct ast_channel *c)
ast_log ( LOG_WARNING , " Usecnt < 0 \n " ) ;
}
ast_mutex_unlock ( & usecnt_lock ) ;
ast_update_use_count ( ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
ast_update_use_count ( ) ;
return 0 ;
}
@ -656,10 +753,17 @@ static struct ast_frame *oh323_rtp_read(struct oh323_pvt *pvt)
/* We already hold the channel lock */
if ( f - > frametype = = AST_FRAME_VOICE ) {
if ( f - > subclass ! = pvt - > owner - > nativeformats ) {
/* Try to avoid deadlock */
if ( ast_mutex_trylock ( & pvt - > owner - > lock ) ) {
ast_log ( LOG_NOTICE , " Format changed but channel is locked. Ignoring frame... \n " ) ;
return & null_frame ;
}
ast_log ( LOG_DEBUG , " Oooh, format changed to %d \n " , f - > subclass ) ;
pvt - > owner - > nativeformats = f - > subclass ;
pvt - > nativeformats = f - > subclass ;
ast_set_read_format ( pvt - > owner , pvt - > owner - > readformat ) ;
ast_set_write_format ( pvt - > owner , pvt - > owner - > writeformat ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
/* Do in-band DTMF detection */
if ( ( pvt - > dtmfmode & H323_DTMF_INBAND ) & & pvt - > vad ) {
@ -679,6 +783,7 @@ static struct ast_frame *oh323_read(struct ast_channel *c)
struct ast_frame * fr ;
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
ast_mutex_lock ( & pvt - > lock ) ;
oh323_update_info ( c ) ;
fr = oh323_rtp_read ( pvt ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
return fr ;
@ -699,7 +804,7 @@ static int oh323_write(struct ast_channel *c, struct ast_frame *frame)
if ( ! ( frame - > subclass & c - > nativeformats ) ) {
ast_log ( LOG_WARNING , " Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d) \n " ,
frame - > subclass , c - > nativeformats , c - > readformat , c - > writeformat ) ;
return - 1 ;
return 0 ;
}
}
if ( pvt ) {
@ -716,47 +821,71 @@ static int oh323_indicate(struct ast_channel *c, int condition)
{
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
char * token = ( char * ) NULL ;
ast_log ( LOG_DEBUG , " OH323: Indicating %d on %s \n " , condition , pvt - > cd . call_token ) ;
ast_mutex_lock ( & pvt - > lock ) ;
token = ( pvt - > cd . call_token ? strdup ( pvt - > cd . call_token ) : NULL ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323debug )
ast_log ( LOG_DEBUG , " OH323: Indicating %d on %s \n " , condition , token ) ;
switch ( condition ) {
case AST_CONTROL_RINGING :
if ( c - > _state = = AST_STATE_RING | | c - > _state = = AST_STATE_RINGING ) {
h323_send_alerting ( pvt - > cd . call_token ) ;
h323_send_alerting ( token) ;
break ;
}
if ( token )
free ( token ) ;
return - 1 ;
case AST_CONTROL_PROGRESS :
if ( c - > _state ! = AST_STATE_UP ) {
h323_send_progress ( pvt- > cd . call_ token) ;
h323_send_progress ( token) ;
break ;
}
if ( token )
free ( token ) ;
return - 1 ;
case AST_CONTROL_BUSY :
if ( c - > _state ! = AST_STATE_UP ) {
h323_answering_call ( pvt- > cd . call_ token, 1 ) ;
h323_answering_call ( token, 1 ) ;
pvt - > alreadygone = 1 ;
ast_softhangup_nolock ( c , AST_SOFTHANGUP_DEV ) ;
break ;
}
if ( token )
free ( token ) ;
return - 1 ;
case AST_CONTROL_CONGESTION :
if ( c - > _state ! = AST_STATE_UP ) {
h323_answering_call ( pvt- > cd . call_ token, 1 ) ;
h323_answering_call ( token, 1 ) ;
pvt - > alreadygone = 1 ;
ast_softhangup_nolock ( c , AST_SOFTHANGUP_DEV ) ;
break ;
}
if ( token )
free ( token ) ;
return - 1 ;
case AST_CONTROL_PROCEEDING :
case - 1 :
if ( token )
free ( token ) ;
return - 1 ;
default :
ast_log ( LOG_WARNING , " Don't know how to indicate condition %d \n " , condition ) ;
ast_log ( LOG_WARNING , " Don't know how to indicate condition %d on %s \n " , condition , token ) ;
if ( token )
free ( token ) ;
return - 1 ;
ast_mutex_unlock ( & pvt - > lock ) ;
}
if ( h323debug )
ast_log ( LOG_DEBUG , " OH323: Indicated %d on %s \n " , condition , token ) ;
if ( token )
free ( token ) ;
oh323_update_info ( c ) ;
return - 1 ;
}
@ -795,6 +924,7 @@ static struct ast_channel *oh323_new(struct oh323_pvt *pvt, int state, const cha
if ( ! ch - > nativeformats ) {
ch - > nativeformats = capability ;
}
pvt - > nativeformats = ch - > nativeformats ;
fmt = ast_best_codec ( ch - > nativeformats ) ;
ch - > type = type ;
ch - > fds [ 0 ] = ast_rtp_fd ( pvt - > rtp ) ;
@ -903,7 +1033,7 @@ static struct oh323_pvt *find_call(int call_reference, const char *token)
ast_mutex_lock ( & iflock ) ;
pvt = iflist ;
while ( pvt ) {
if ( ( signed int ) pvt - > cd . call_reference = = call_reference ) {
if ( ! pvt - > needdestroy & & ( ( signed int ) pvt - > cd . call_reference = = call_reference ) ) {
/* Found the call */
if ( ( token ! = NULL ) & & ( ! strcmp ( pvt - > cd . call_token , token ) ) ) {
ast_mutex_unlock ( & iflock ) ;
@ -1173,8 +1303,10 @@ struct rtp_info *external_rtp_create(unsigned call_reference, const char * token
ast_log ( LOG_ERROR , " Unable to find call %s(%d) \n " , token , call_reference ) ;
return NULL ;
}
ast_mutex_lock ( & pvt - > lock ) ;
/* figure out our local RTP port and tell the H.323 stack about it */
ast_rtp_get_us ( pvt - > rtp , & us ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
/* evil hack, until I (or someone?) figures out a better way */
info - > addr = ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , bindaddr . sin_addr ) ;
info - > port = ntohs ( us . sin_port ) ;
@ -1202,26 +1334,28 @@ void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int rem
struct oh323_pvt * pvt = NULL ;
struct sockaddr_in them ;
struct rtpPayloadType rtptype ;
int fmt ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Setting up RTP connection for %s \n " , token ) ;
/* Find the call or allocate a private structure if call not found */
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: rtp \n " ) ;
return ;
}
rtptype = ast_rtp_lookup_pt ( pvt - > rtp , pt ) ;
fmt = ast_best_codec ( pvt - > owner - > nativeformats ) ;
ast_mutex_lock ( & pvt - > lock ) ;
pvt - > owner - > nativeformats = rtptype . code ;
pvt - > owner - > readformat = fmt ;
pvt - > owner - > writeformat = fmt ;
ast_set_read_format ( pvt - > owner , pvt - > owner - > readformat ) ;
ast_set_write_format ( pvt - > owner , pvt - > owner - > writeformat ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
if ( pvt - > alreadygone ) {
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
rtptype = ast_rtp_lookup_pt ( pvt - > rtp , pt ) ;
pvt - > nativeformats = rtptype . code ;
if ( pvt - > owner & & ! ast_mutex_trylock ( & pvt - > owner - > lock ) ) {
pvt - > owner - > nativeformats = pvt - > nativeformats ;
ast_set_read_format ( pvt - > owner , pvt - > owner - > readformat ) ;
ast_set_write_format ( pvt - > owner , pvt - > owner - > writeformat ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
them . sin_family = AF_INET ;
/* only works for IPv4 */
@ -1230,8 +1364,13 @@ void setup_rtp_connection(unsigned call_reference, const char *remoteIp, int rem
ast_rtp_set_peer ( pvt - > rtp , & them ) ;
if ( pvt - > options . progress_audio ) {
ast_mutex_unlock ( & pvt - > lock ) ;
progress ( call_reference , token , 1 ) ;
}
} else
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323debug )
ast_log ( LOG_DEBUG , " RTP connection prepared for %s \n " , token ) ;
return ;
}
@ -1244,6 +1383,9 @@ void connection_made(unsigned call_reference, const char *token)
{
struct ast_channel * c = NULL ;
struct oh323_pvt * pvt = NULL ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Call %s answered \n " , token ) ;
pvt = find_call ( call_reference , token ) ;
@ -1252,13 +1394,23 @@ void connection_made(unsigned call_reference, const char *token)
return ;
}
ast_mutex_lock ( & pvt - > lock ) ;
/* Inform asterisk about remote party connected only on outgoing calls */
if ( ! pvt - > outgoing ) {
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
if ( ! pvt - > owner ) {
ast_mutex_unlock ( & pvt - > lock ) ;
ast_log ( LOG_ERROR , " Channel has no owner \n " ) ;
return ;
}
ast_mutex_lock ( & pvt - > owner - > lock ) ;
c = pvt - > owner ;
ast_setstate ( c , AST_STATE_UP ) ;
ast_queue_control ( c , AST_CONTROL_ANSWER ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
@ -1273,12 +1425,16 @@ int progress(unsigned call_reference, const char *token, int inband)
ast_log ( LOG_ERROR , " Private structure not found in progress. \n " ) ;
return - 1 ;
}
ast_mutex_lock ( & p - > lock ) ;
if ( ! p - > owner ) {
ast_mutex_unlock ( & p - > lock ) ;
ast_log ( LOG_ERROR , " No Asterisk channel associated with private structure. \n " ) ;
return - 1 ;
}
ast_mutex_lock ( & p - > owner - > lock ) ;
ast_queue_control ( p - > owner , ( inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING ) ) ;
ast_mutex_unlock ( & p - > owner - > lock ) ;
ast_mutex_unlock ( & p - > lock ) ;
return 0 ;
}
@ -1293,9 +1449,12 @@ call_options_t *setup_incoming_call(call_details_t cd)
struct oh323_pvt * pvt = NULL ;
struct oh323_user * user = NULL ;
struct oh323_alias * alias = NULL ;
call_options_t * call_options = NULL ;
call_options_t * call_options ;
char iabuf [ INET_ADDRSTRLEN ] ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Setting up incoming call for %s \n " , cd . call_token ) ;
/* allocate the call*/
pvt = oh323_alloc ( cd . call_reference ) ;
@ -1311,6 +1470,7 @@ call_options_t *setup_incoming_call(call_details_t cd)
pvt - > cd . call_source_name = strdup ( cd . call_source_name ) ;
pvt - > cd . call_source_e164 = strdup ( cd . call_source_e164 ) ;
pvt - > cd . call_dest_e164 = strdup ( cd . call_dest_e164 ) ;
call_options = & pvt - > options ;
if ( h323debug ) {
ast_verbose ( VERBOSE_PREFIX_3 " Setting up Call \n " ) ;
@ -1367,7 +1527,7 @@ call_options_t *setup_incoming_call(call_details_t cd)
pvt - > exten [ 0 ] = ' i ' ;
pvt - > exten [ 1 ] = ' \0 ' ;
ast_log ( LOG_ERROR , " Call from '%s' rejected due to non-matching IP address (%s)s \n " , user - > name , cd . sourceIp ) ;
goto exit ;
return NULL ;
}
}
strncpy ( pvt - > context , user - > context , sizeof ( pvt - > context ) - 1 ) ;
@ -1387,7 +1547,6 @@ call_options_t *setup_incoming_call(call_details_t cd)
call_options = & user - > options ;
}
}
exit :
return call_options ;
}
@ -1401,6 +1560,9 @@ static int answer_call(unsigned call_reference, const char *token)
struct oh323_pvt * pvt = NULL ;
struct ast_channel * c = NULL ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Preparing Asterisk to answer for %s \n " , token ) ;
/* Find the call or allocate a private structure if call not found */
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
@ -1441,79 +1603,112 @@ void chan_ringing(unsigned call_reference, const char *token)
struct ast_channel * c = NULL ;
struct oh323_pvt * pvt = NULL ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Ringing on %s \n " , token ) ;
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: ringing \n " ) ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( ! pvt - > owner ) {
ast_mutex_unlock ( & pvt - > lock ) ;
ast_log ( LOG_ERROR , " Channel has no owner \n " ) ;
return ;
}
ast_mutex_lock ( & pvt - > owner - > lock ) ;
c = pvt - > owner ;
ast_setstate ( c , AST_STATE_RINGING ) ;
ast_queue_control ( c , AST_CONTROL_RINGING ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
void cleanup_call_details ( call_details_t cd )
{
if ( cd . call_token ) {
free ( cd . call_token ) ;
}
if ( cd . call_source_aliases ) {
free ( cd . call_source_aliases ) ;
}
if ( cd . call_dest_alias ) {
free ( cd . call_dest_alias ) ;
}
if ( cd . call_source_name ) {
free ( cd . call_source_name ) ;
}
if ( cd . call_source_e164 ) {
free ( cd . call_source_e164 ) ;
}
if ( cd . call_dest_e164 ) {
free ( cd . call_dest_e164 ) ;
}
if ( cd . sourceIp ) {
free ( cd . sourceIp ) ;
}
}
/**
* Call - back function to cleanup communication
* Returns nothing ,
*/
void cleanup_connection ( call_details_t cd )
static void cleanup_connection ( call_details_t cd )
{
struct oh323_pvt * pvt = NULL ;
struct ast_rtp * rtp = NULL ;
ast_log ( LOG_DEBUG , " Cleaning connection to %s \n " , cd . call_token ) ;
pvt = find_call ( cd . call_reference , cd . call_token ) ;
if ( ! pvt ) {
return ;
while ( 1 ) {
pvt = find_call ( cd . call_reference , cd . call_token ) ;
if ( ! pvt ) {
return ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( ! pvt - > owner | | ! ast_mutex_trylock ( & pvt - > owner - > lock ) )
break ;
# if 1
# ifdef DEBUG_THREADS
ast_log ( LOG_NOTICE , " Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d) \n " , cd . call_token , pvt - > owner - > lock . thread , pvt - > owner - > lock . reentrancy , pvt - > owner - > lock . func , pvt - > owner - > lock . file , pvt - > owner - > lock . lineno ) ;
# else
ast_log ( LOG_NOTICE , " Avoiding H.323 destory deadlock on %s \n " , cd . call_token ) ;
# endif
# endif
ast_mutex_unlock ( & pvt - > lock ) ;
usleep ( 1 ) ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( pvt - > rtp ) {
rtp = pvt - > rtp ;
pvt - > rtp = NULL ;
/* Immediately stop RTP */
ast_rtp_destroy ( rtp ) ;
}
cleanup_call_details ( pvt - > cd ) ;
/* Free dsp used for in-band DTMF detection */
if ( pvt - > vad ) {
ast_dsp_free ( pvt - > vad ) ;
pvt - > vad = NULL ;
}
cleanup_call_details ( & pvt - > cd ) ;
pvt - > alreadygone = 1 ;
/* Send hangup */
if ( pvt - > owner ) {
pvt - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
ast_queue_hangup ( pvt - > owner ) ;
}
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
static void hangup_connection ( unsigned int call_reference , const char * token , int cause )
{
struct oh323_pvt * pvt = NULL ;
ast_log ( LOG_DEBUG , " Hanging up connection to %s with cause %d \n " , token , cause ) ;
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
return ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( pvt - > owner & & ! ast_mutex_trylock ( & pvt - > owner - > lock ) ) {
pvt - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
pvt - > owner - > hangupcause = pvt - > hangupcause = cause ;
ast_queue_hangup ( pvt - > owner ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
else {
pvt - > needhangup = 1 ;
pvt - > hangupcause = cause ;
ast_log ( LOG_DEBUG , " Hangup for %s is pending \n " , token ) ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
}
void set_dtmf_payload ( unsigned call_reference , const char * token , int payload )
{
struct oh323_pvt * pvt = NULL ;
if ( h323debug )
ast_log ( LOG_DEBUG , " Setting DTMF payload to %d on %s \n " , payload , token ) ;
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
return ;
@ -1523,6 +1718,8 @@ void set_dtmf_payload(unsigned call_reference, const char *token, int payload)
ast_rtp_set_rtpmap_type ( pvt - > rtp , payload , " audio " , " telephone-event " ) ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323debug )
ast_log ( LOG_DEBUG , " DTMF payload on %s set to %d \n " , token , payload ) ;
}
static void * do_monitor ( void * data )
@ -1562,6 +1759,7 @@ restartsearch:
res = 1000 ;
}
res = ast_io_wait ( io , res ) ;
pthread_testcancel ( ) ;
ast_mutex_lock ( & monlock ) ;
if ( res > = 0 ) {
ast_sched_runq ( sched ) ;
@ -2124,7 +2322,8 @@ int load_module()
send_digit ,
answer_call ,
progress ,
set_dtmf_payload ) ;
set_dtmf_payload ,
hangup_connection ) ;
/* start the h.323 listener */
if ( h323_start_listener ( h323_signalling_port , bindaddr ) ) {
ast_log ( LOG_ERROR , " Unable to create H323 listener. \n " ) ;