2003-03-31 07:13:36 +00:00
/*
2005-09-15 15:44:26 +00:00
* Asterisk - - An open source telephony toolkit .
*
* Copyright ( C ) 1999 - 2005
2003-03-31 07:13:36 +00:00
*
* OpenH323 Channel Driver for ASTERISK PBX .
* By Jeremy McNamara
2006-09-19 17:07:22 +00:00
* For The NuFone Network
2003-03-31 07:13:36 +00:00
*
2004-09-30 19:36:46 +00:00
* chan_h323 has been derived from code created by
* Michael Manousos and Mark Spencer
2003-03-31 07:13:36 +00:00
*
2005-09-15 15:44:26 +00:00
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
* the project provides a web site , mailing lists and IRC
* channels for your use .
2003-03-31 07:13:36 +00:00
*
2005-09-15 15:44:26 +00:00
* This program is free software , distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
*/
2005-10-24 20:12:06 +00:00
/*! \file
2003-03-31 07:13:36 +00:00
*
2005-10-24 20:12:06 +00:00
* \ brief This file is part of the chan_h323 driver for Asterisk
2003-03-31 07:13:36 +00:00
*
2005-12-30 21:18:06 +00:00
* \ author Jeremy McNamara
*
2005-11-06 15:09:47 +00:00
* \ par See also
* \ arg Config_h323
2007-03-12 09:37:13 +00:00
* \ extref OpenH323 http : //www.voxgratia.org/
2005-11-06 15:09:47 +00:00
*
* \ ingroup channel_drivers
2003-03-31 07:13:36 +00:00
*/
2006-04-24 17:11:45 +00:00
/*** MODULEINFO
2006-09-19 17:07:22 +00:00
< depend > openh323 < / depend >
2007-02-01 11:16:00 +00:00
< defaultenabled > yes < / defaultenabled >
2006-04-24 17:11:45 +00:00
* * */
2006-06-07 18:54:56 +00:00
# ifdef __cplusplus
extern " C " {
2006-09-19 17:07:22 +00:00
# endif
2006-06-07 18:54:56 +00:00
# include "asterisk.h"
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
# ifdef __cplusplus
}
# endif
2007-12-27 17:34:00 +00:00
# include <sys/types.h>
2004-06-26 03:50:14 +00:00
# include <sys/socket.h>
# include <sys/signal.h>
# include <sys/param.h>
# include <arpa/inet.h>
# include <net/if.h>
# include <netinet/in.h>
# include <netinet/in_systm.h>
# include <netinet/ip.h>
# include <netdb.h>
# include <fcntl.h>
2006-06-07 18:54:56 +00:00
2004-06-26 03:50:14 +00:00
# ifdef __cplusplus
extern " C " {
2006-09-19 17:07:22 +00:00
# endif
2005-06-06 21:09:59 +00:00
2005-04-21 06:02:45 +00:00
# include "asterisk/lock.h"
# include "asterisk/channel.h"
# include "asterisk/config.h"
# include "asterisk/module.h"
2006-09-19 17:07:22 +00:00
# include "asterisk/musiconhold.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/pbx.h"
# include "asterisk/utils.h"
# include "asterisk/sched.h"
# include "asterisk/io.h"
# include "asterisk/rtp.h"
# include "asterisk/acl.h"
# include "asterisk/callerid.h"
# include "asterisk/cli.h"
# include "asterisk/dsp.h"
# include "asterisk/causes.h"
2006-04-03 18:36:30 +00:00
# include "asterisk/stringfields.h"
2006-06-01 16:47:28 +00:00
# include "asterisk/abstract_jb.h"
2006-09-19 17:07:22 +00:00
# include "asterisk/astobj.h"
2006-06-07 18:54:56 +00:00
2004-06-26 03:50:14 +00:00
# ifdef __cplusplus
}
2004-04-19 08:11:51 +00:00
# endif
2006-06-07 18:54:56 +00:00
2003-08-16 17:00:22 +00:00
# include "h323/chan_h323.h"
2003-03-31 07:13:36 +00:00
2006-09-19 17:07:22 +00:00
receive_digit_cb on_receive_digit ;
on_rtp_cb on_external_rtp_create ;
start_rtp_cb on_start_rtp_channel ;
2004-09-30 19:36:46 +00:00
setup_incoming_cb on_incoming_call ;
2006-09-19 17:07:22 +00:00
setup_outbound_cb on_outgoing_call ;
2004-09-30 19:36:46 +00:00
chan_ringing_cb on_chan_ringing ;
con_established_cb on_connection_established ;
clear_con_cb on_connection_cleared ;
answer_call_cb on_answer_call ;
2004-12-15 23:24:13 +00:00
progress_cb on_progress ;
rfc2833_cb on_set_rfc2833_payload ;
2005-04-04 15:54:34 +00:00
hangup_cb on_hangup ;
2005-05-19 19:13:19 +00:00
setcapabilities_cb on_setcapabilities ;
2006-09-19 17:07:22 +00:00
setpeercapabilities_cb on_setpeercapabilities ;
2006-09-28 10:41:38 +00:00
onhold_cb on_hold ;
2004-09-30 19:36:46 +00:00
2007-02-24 20:29:41 +00:00
int h323debug ; /*!< global debug flag */
2004-06-26 03:50:14 +00:00
2007-02-24 20:29:41 +00:00
/*! \brief Global jitterbuffer configuration - by default, jb is disabled */
2006-06-01 16:47:28 +00:00
static struct ast_jb_conf default_jbconf =
{
. flags = 0 ,
. max_size = - 1 ,
. resync_threshold = - 1 ,
. impl = " "
} ;
static struct ast_jb_conf global_jbconf ;
2004-09-30 19:36:46 +00:00
/** Variables required by Asterisk */
2006-09-19 17:07:22 +00:00
static const char tdesc [ ] = " The NuFone Network's Open H.323 Channel Driver " ;
2005-03-04 06:47:24 +00:00
static const char config [ ] = " h323.conf " ;
2005-07-10 23:49:57 +00:00
static char default_context [ AST_MAX_CONTEXT ] = " default " ;
2004-12-15 23:24:13 +00:00
static struct sockaddr_in bindaddr ;
2003-03-31 07:13:36 +00:00
2006-09-21 18:48:53 +00:00
# define GLOBAL_CAPABILITY (AST_FORMAT_G723_1 | AST_FORMAT_GSM | AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_G729A | AST_FORMAT_G726_AAL2 | AST_FORMAT_H261)
2006-04-03 18:36:30 +00:00
2003-03-31 07:13:36 +00:00
/** H.323 configuration values */
2004-10-04 10:13:01 +00:00
static int h323_signalling_port = 1720 ;
2003-03-31 07:13:36 +00:00
static char gatekeeper [ 100 ] ;
2004-09-30 19:36:46 +00:00
static int gatekeeper_disable = 1 ;
static int gatekeeper_discover = 0 ;
static int gkroute = 0 ;
/* Find user by alias (h.323 id) is default, alternative is the incomming call's source IP address*/
2004-10-28 06:06:58 +00:00
static int userbyalias = 1 ;
2006-09-19 17:07:22 +00:00
static int acceptAnonymous = 1 ;
2007-04-30 16:16:26 +00:00
static unsigned int tos = 0 ;
static unsigned int cos = 0 ;
2003-03-31 07:13:36 +00:00
static char secret [ 50 ] ;
2005-05-11 13:27:49 +00:00
static unsigned int unique = 0 ;
2003-03-31 07:13:36 +00:00
2004-12-15 23:24:13 +00:00
static call_options_t global_options ;
2007-02-24 20:29:41 +00:00
/*! \brief Private structure of a OpenH323 channel */
2003-03-31 07:13:36 +00:00
struct oh323_pvt {
2007-02-24 20:29:41 +00:00
ast_mutex_t lock ; /*!< Channel private lock */
call_options_t options ; /*!<!< Options to be used during call setup */
int alreadygone ; /*!< Whether or not we've already been destroyed by our peer */
int needdestroy ; /*!< if we need to be destroyed */
call_details_t cd ; /*!< Call details */
struct ast_channel * owner ; /*!< Who owns us */
struct sockaddr_in sa ; /*!< Our peer */
struct sockaddr_in redirip ; /*!< Where our RTP should be going if not to us */
int nonCodecCapability ; /*!< non-audio capability */
int outgoing ; /*!< Outgoing or incoming call? */
char exten [ AST_MAX_EXTENSION ] ; /*!< Requested extension */
char context [ AST_MAX_CONTEXT ] ; /*!< Context where to start */
char accountcode [ 256 ] ; /*!< Account code */
char rdnis [ 80 ] ; /*!< Referring DNIS, if available */
int amaflags ; /*!< AMA Flags */
struct ast_rtp * rtp ; /*!< RTP Session */
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 */
int newstate ; /*!< Pending state change */
int newcontrol ; /*!< Pending control to send */
int newdigit ; /*!< Pending DTMF digit to send */
int newduration ; /*!< Pending DTMF digit duration to send */
int pref_codec ; /*!< Preferred codec */
int peercapability ; /*!< Capabilities learned from peer */
int jointcapability ; /*!< Common capabilities for local and remote side */
struct ast_codec_pref peer_prefs ; /*!< Preferenced list of codecs which remote side supports */
int dtmf_pt [ 2 ] ; /*!< Payload code used for RFC2833/CISCO messages */
int curDTMF ; /*!< DTMF tone being generated to Asterisk side */
int DTMFsched ; /*!< Scheduler descriptor for DTMF */
int update_rtp_info ; /*!< Configuration of fd's array is pending */
int recvonly ; /*!< Peer isn't wish to receive our voice stream */
int txDtmfDigit ; /*!< DTMF digit being to send to H.323 side */
int noInbandDtmf ; /*!< Inband DTMF processing by DSP isn't available */
int connection_established ; /*!< Call got CONNECT message */
int got_progress ; /*!< Call got PROGRESS message, pass inband audio */
struct oh323_pvt * next ; /*!< Next channel in list */
2003-03-31 07:13:36 +00:00
} * iflist = NULL ;
2007-02-24 20:29:41 +00:00
/*! \brief H323 User list */
static struct h323_user_list {
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_COMPONENTS ( struct oh323_user ) ;
2004-06-12 03:44:51 +00:00
} userl ;
2003-03-31 07:13:36 +00:00
2007-02-24 20:29:41 +00:00
/*! \brief H323 peer list */
static struct h323_peer_list {
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_COMPONENTS ( struct oh323_peer ) ;
2004-06-12 03:44:51 +00:00
} peerl ;
2003-03-31 07:13:36 +00:00
2007-02-24 20:29:41 +00:00
/*! \brief H323 alias list */
static struct h323_alias_list {
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_COMPONENTS ( struct oh323_alias ) ;
2004-06-12 03:44:51 +00:00
} aliasl ;
2003-03-31 07:13:36 +00:00
2007-02-24 20:29:41 +00:00
/* Asterisk RTP stuff */
2003-03-31 07:13:36 +00:00
static struct sched_context * sched ;
static struct io_context * io ;
2007-02-24 20:29:41 +00:00
AST_MUTEX_DEFINE_STATIC ( iflock ) ; /*!< Protect the interface list (oh323_pvt) */
2003-03-31 07:13:36 +00:00
2007-02-24 20:29:41 +00:00
/*! \brief Protect the H.323 monitoring thread, so only one process can kill or start it, and not
2003-03-31 07:13:36 +00:00
when it ' s doing something critical . */
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( monlock ) ;
2003-03-31 07:13:36 +00:00
2007-02-24 20:29:41 +00:00
/*! \brief Protect the H.323 capabilities list, to avoid more than one channel to set the capabilities simultaneaously in the h323 stack. */
2004-07-30 20:01:58 +00:00
AST_MUTEX_DEFINE_STATIC ( caplock ) ;
2007-02-24 20:29:41 +00:00
/*! \brief Protect the reload process */
2004-10-15 07:07:50 +00:00
AST_MUTEX_DEFINE_STATIC ( h323_reload_lock ) ;
static int h323_reloading = 0 ;
2007-02-24 20:29:41 +00:00
/*! \brief This is the thread for the monitor which checks for input on the channels
2006-09-19 17:07:22 +00:00
which are not currently in use . */
2004-03-15 07:51:22 +00:00
static pthread_t monitor_thread = AST_PTHREADT_NULL ;
2003-03-31 07:13:36 +00:00
static int restart_monitor ( void ) ;
2004-10-15 07:07:50 +00:00
static int h323_do_reload ( void ) ;
2003-03-31 07:13:36 +00:00
2007-08-20 00:37:12 +00:00
static void delete_users ( void ) ;
static void delete_aliases ( void ) ;
static void prune_peers ( void ) ;
2005-03-04 06:47:24 +00:00
static struct ast_channel * oh323_request ( const char * type , int format , void * data , int * cause ) ;
2006-08-31 01:59:02 +00:00
static int oh323_digit_begin ( struct ast_channel * c , char digit ) ;
Merged revisions 51311 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r51311 | russell | 2007-01-19 11:49:38 -0600 (Fri, 19 Jan 2007) | 23 lines
Merge the changes from the /team/group/vldtmf_fixup branch.
The main bug being addressed here is a problem introduced when two SIP
channels using SIP INFO dtmf have their media directly bridged. So, when a
DTMF END frame comes into Asterisk from an incoming INFO message, Asterisk
would try to emulate a digit of some length by first sending a DTMF BEGIN
frame and sending a DTMF END later timed off of incoming audio. However,
since there was no audio coming in, the DTMF_END was never generated. This
caused DTMF based features to no longer work.
To fix this, the core now knows when a channel doesn't care about DTMF BEGIN
frames (such as a SIP channel sending INFO dtmf). If this is the case, then
Asterisk will not emulate a digit of some length, and will instead just pass
through the single DTMF END event.
Channel drivers also now get passed the length of the digit to their digit_end
callback. This improves SIP INFO support even further by enabling us to put
the real digit duration in the INFO message instead of a hard coded 250ms.
Also, for an incoming INFO message, the duration is read from the frame and
passed into the core instead of just getting ignored.
(issue #8597, maybe others...)
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@51314 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-19 18:06:03 +00:00
static int oh323_digit_end ( struct ast_channel * c , char digit , unsigned int duration ) ;
2005-03-04 06:47:24 +00:00
static int oh323_call ( struct ast_channel * c , char * dest , int timeout ) ;
static int oh323_hangup ( struct ast_channel * c ) ;
static int oh323_answer ( struct ast_channel * c ) ;
static struct ast_frame * oh323_read ( struct ast_channel * c ) ;
static int oh323_write ( struct ast_channel * c , struct ast_frame * frame ) ;
2006-05-10 15:00:33 +00:00
static int oh323_indicate ( struct ast_channel * c , int condition , const void * data , size_t datalen ) ;
2005-03-04 06:47:24 +00:00
static int oh323_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan ) ;
static const struct ast_channel_tech oh323_tech = {
2006-04-03 18:36:30 +00:00
. type = " H323 " ,
2005-03-04 06:47:24 +00:00
. description = tdesc ,
2007-11-06 22:51:48 +00:00
. capabilities = AST_FORMAT_AUDIO_MASK ,
2006-05-31 17:21:21 +00:00
. properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER ,
2005-03-04 06:47:24 +00:00
. requester = oh323_request ,
2006-08-31 01:59:02 +00:00
. send_digit_begin = oh323_digit_begin ,
. send_digit_end = oh323_digit_end ,
2005-03-04 06:47:24 +00:00
. call = oh323_call ,
. hangup = oh323_hangup ,
. answer = oh323_answer ,
. read = oh323_read ,
. write = oh323_write ,
. indicate = oh323_indicate ,
. fixup = oh323_fixup ,
. bridge = ast_rtp_bridge ,
} ;
2006-09-19 17:07:22 +00:00
static const char * redirectingreason2str ( int redirectingreason )
{
switch ( redirectingreason ) {
case 0 :
return " UNKNOWN " ;
case 1 :
return " BUSY " ;
case 2 :
return " NO_REPLY " ;
case 0xF :
return " UNCONDITIONAL " ;
default :
return " NOREDIRECT " ;
}
}
static void oh323_destroy_alias ( struct oh323_alias * alias )
{
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Destroying alias '%s' \n " , alias - > name ) ;
2007-06-03 06:10:27 +00:00
ast_free ( alias ) ;
2006-09-19 17:07:22 +00:00
}
static void oh323_destroy_user ( struct oh323_user * user )
{
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Destroying user '%s' \n " , user - > name ) ;
2006-09-19 17:07:22 +00:00
ast_free_ha ( user - > ha ) ;
2007-06-03 06:10:27 +00:00
ast_free ( user ) ;
2006-09-19 17:07:22 +00:00
}
static void oh323_destroy_peer ( struct oh323_peer * peer )
{
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Destroying peer '%s' \n " , peer - > name ) ;
2006-09-19 17:07:22 +00:00
ast_free_ha ( peer - > ha ) ;
2007-06-03 06:10:27 +00:00
ast_free ( peer ) ;
2006-09-19 17:07:22 +00:00
}
2007-09-21 14:40:10 +00:00
static int oh323_simulate_dtmf_end ( const void * data )
2006-09-19 17:07:22 +00:00
{
2007-09-21 14:40:10 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) data ;
2006-09-19 17:07:22 +00:00
if ( pvt ) {
ast_mutex_lock ( & pvt - > lock ) ;
/* Don't hold pvt lock while trying to lock the channel */
while ( pvt - > owner & & ast_channel_trylock ( pvt - > owner ) ) {
2008-06-25 02:34:11 +00:00
DEADLOCK_AVOIDANCE ( & pvt - > lock ) ;
2006-09-19 17:07:22 +00:00
}
if ( pvt - > owner ) {
struct ast_frame f = {
. frametype = AST_FRAME_DTMF_END ,
. subclass = pvt - > curDTMF ,
. samples = 0 ,
. src = " SIMULATE_DTMF_END " ,
} ;
ast_queue_frame ( pvt - > owner , & f ) ;
ast_channel_unlock ( pvt - > owner ) ;
}
pvt - > DTMFsched = - 1 ;
ast_mutex_unlock ( & pvt - > lock ) ;
}
return 0 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief Channel and private structures should be already locked */
2005-05-11 13:27:49 +00:00
static void __oh323_update_info ( struct ast_channel * c , struct oh323_pvt * pvt )
2005-04-04 15:54:34 +00:00
{
if ( c - > nativeformats ! = pvt - > nativeformats ) {
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Preparing %s for new native format \n " , c - > name ) ;
2005-04-04 15:54:34 +00:00
c - > nativeformats = pvt - > nativeformats ;
ast_set_read_format ( c , c - > readformat ) ;
ast_set_write_format ( c , c - > writeformat ) ;
}
if ( pvt - > needhangup ) {
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Process pending hangup for %s \n " , c - > name ) ;
2005-04-04 15:54:34 +00:00
c - > _softhangup | = AST_SOFTHANGUP_DEV ;
c - > hangupcause = pvt - > hangupcause ;
2008-05-22 16:29:54 +00:00
ast_queue_hangup_with_cause ( c , pvt - > hangupcause ) ;
2005-04-04 15:54:34 +00:00
pvt - > needhangup = 0 ;
2006-09-19 17:07:22 +00:00
pvt - > newstate = pvt - > newcontrol = pvt - > newdigit = pvt - > DTMFsched = - 1 ;
2005-07-27 04:45:11 +00:00
}
if ( pvt - > newstate > = 0 ) {
ast_setstate ( c , pvt - > newstate ) ;
pvt - > newstate = - 1 ;
}
if ( pvt - > newcontrol > = 0 ) {
ast_queue_control ( c , pvt - > newcontrol ) ;
pvt - > newcontrol = - 1 ;
2005-04-04 15:54:34 +00:00
}
2006-08-15 14:55:30 +00:00
if ( pvt - > newdigit > = 0 ) {
2006-08-15 17:14:20 +00:00
struct ast_frame f = {
2006-09-19 17:07:22 +00:00
. frametype = AST_FRAME_DTMF_END ,
2006-08-15 17:14:20 +00:00
. subclass = pvt - > newdigit ,
2006-09-19 17:07:22 +00:00
. samples = pvt - > newduration * 8 ,
2007-02-10 09:23:09 +00:00
. len = pvt - > newduration ,
2006-08-15 17:14:20 +00:00
. src = " UPDATE_INFO " ,
} ;
2006-09-19 17:07:22 +00:00
if ( pvt - > newdigit = = ' ' ) { /* signalUpdate message */
f . subclass = pvt - > curDTMF ;
if ( pvt - > DTMFsched > = 0 ) {
2008-01-27 22:35:29 +00:00
AST_SCHED_DEL ( sched , pvt - > DTMFsched ) ;
2006-09-19 17:07:22 +00:00
}
} else { /* Regular input or signal message */
if ( pvt - > newduration ) { /* This is a signal, signalUpdate follows */
f . frametype = AST_FRAME_DTMF_BEGIN ;
2008-01-27 22:35:29 +00:00
AST_SCHED_DEL ( sched , pvt - > DTMFsched ) ;
2006-09-19 17:07:22 +00:00
pvt - > DTMFsched = ast_sched_add ( sched , pvt - > newduration , oh323_simulate_dtmf_end , pvt ) ;
if ( h323debug )
ast_log ( LOG_DTMF , " Scheduled DTMF END simulation for %d ms, id=%d \n " , pvt - > newduration , pvt - > DTMFsched ) ;
}
pvt - > curDTMF = pvt - > newdigit ;
}
2006-08-15 14:55:30 +00:00
ast_queue_frame ( c , & f ) ;
pvt - > newdigit = - 1 ;
}
2006-09-19 17:07:22 +00:00
if ( pvt - > update_rtp_info > 0 ) {
if ( pvt - > rtp ) {
ast_jb_configure ( c , & global_jbconf ) ;
2007-08-08 21:44:58 +00:00
ast_channel_set_fd ( c , 0 , ast_rtp_fd ( pvt - > rtp ) ) ;
ast_channel_set_fd ( c , 1 , ast_rtcp_fd ( pvt - > rtp ) ) ;
2006-09-19 17:07:22 +00:00
ast_queue_frame ( pvt - > owner , & ast_null_frame ) ; /* Tell Asterisk to apply changes */
}
pvt - > update_rtp_info = - 1 ;
}
2005-05-11 13:27:49 +00:00
}
2007-02-24 20:29:41 +00:00
/*! \brief Only channel structure should be locked */
2005-05-11 13:27:49 +00:00
static void oh323_update_info ( struct ast_channel * c )
{
struct oh323_pvt * pvt = c - > tech_pvt ;
if ( pvt ) {
ast_mutex_lock ( & pvt - > lock ) ;
__oh323_update_info ( c , pvt ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
}
2005-04-04 15:54:34 +00:00
}
2006-09-19 17:07:22 +00:00
static void cleanup_call_details ( call_details_t * cd )
{
if ( cd - > call_token ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > call_token ) ;
2006-09-19 17:07:22 +00:00
cd - > call_token = NULL ;
}
if ( cd - > call_source_aliases ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > call_source_aliases ) ;
2006-09-19 17:07:22 +00:00
cd - > call_source_aliases = NULL ;
}
if ( cd - > call_dest_alias ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > call_dest_alias ) ;
2006-09-19 17:07:22 +00:00
cd - > call_dest_alias = NULL ;
}
if ( cd - > call_source_name ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > call_source_name ) ;
2006-09-19 17:07:22 +00:00
cd - > call_source_name = NULL ;
}
if ( cd - > call_source_e164 ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > call_source_e164 ) ;
2006-09-19 17:07:22 +00:00
cd - > call_source_e164 = NULL ;
}
if ( cd - > call_dest_e164 ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > call_dest_e164 ) ;
2006-09-19 17:07:22 +00:00
cd - > call_dest_e164 = NULL ;
}
if ( cd - > sourceIp ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > sourceIp ) ;
2006-09-19 17:07:22 +00:00
cd - > sourceIp = NULL ;
}
if ( cd - > redirect_number ) {
2007-06-03 06:10:27 +00:00
ast_free ( cd - > redirect_number ) ;
2006-09-19 17:07:22 +00:00
cd - > redirect_number = NULL ;
}
2005-04-04 15:54:34 +00:00
}
2005-05-11 13:27:49 +00:00
static void __oh323_destroy ( struct oh323_pvt * pvt )
2003-03-31 07:13:36 +00:00
{
struct oh323_pvt * cur , * prev = NULL ;
2006-09-19 17:07:22 +00:00
2008-01-27 22:35:29 +00:00
AST_SCHED_DEL ( sched , pvt - > DTMFsched ) ;
2006-09-19 17:07:22 +00:00
2005-05-11 13:27:49 +00:00
if ( pvt - > rtp ) {
ast_rtp_destroy ( pvt - > rtp ) ;
2003-03-31 07:13:36 +00:00
}
2006-09-19 17:07:22 +00:00
2005-04-04 15:54:34 +00:00
/* Free dsp used for in-band DTMF detection */
2005-05-11 13:27:49 +00:00
if ( pvt - > vad ) {
ast_dsp_free ( pvt - > vad ) ;
2005-04-04 15:54:34 +00:00
}
2005-05-11 13:27:49 +00:00
cleanup_call_details ( & pvt - > cd ) ;
2005-04-04 15:54:34 +00:00
2003-03-31 07:13:36 +00:00
/* Unlink us from the owner if we have one */
2005-05-11 13:27:49 +00:00
if ( pvt - > owner ) {
2006-09-19 17:07:22 +00:00
ast_channel_lock ( pvt - > owner ) ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Detaching from %s \n " , pvt - > owner - > name ) ;
2005-05-11 13:27:49 +00:00
pvt - > owner - > tech_pvt = NULL ;
2006-09-19 17:07:22 +00:00
ast_channel_unlock ( pvt - > owner ) ;
2003-03-31 07:13:36 +00:00
}
cur = iflist ;
while ( cur ) {
2005-05-11 13:27:49 +00:00
if ( cur = = pvt ) {
2003-03-31 07:13:36 +00:00
if ( prev )
prev - > next = cur - > next ;
else
iflist = cur - > next ;
break ;
}
prev = cur ;
cur = cur - > next ;
}
if ( ! cur ) {
ast_log ( LOG_WARNING , " %p is not in list?!?! \n " , cur ) ;
2004-06-22 17:42:14 +00:00
} else {
2006-09-19 17:07:22 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-05-11 13:27:49 +00:00
ast_mutex_destroy ( & pvt - > lock ) ;
2007-06-03 06:10:27 +00:00
ast_free ( pvt ) ;
2005-05-11 13:27:49 +00:00
}
2003-03-31 07:13:36 +00:00
}
2005-05-11 13:27:49 +00:00
static void oh323_destroy ( struct oh323_pvt * pvt )
2003-03-31 07:13:36 +00:00
{
2006-09-19 17:07:22 +00:00
if ( h323debug ) {
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Destroying channel %s \n " , ( pvt - > owner ? pvt - > owner - > name : " <unknown> " ) ) ;
2006-09-19 17:07:22 +00:00
}
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & iflock ) ;
2006-09-19 17:07:22 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2005-05-11 13:27:49 +00:00
__oh323_destroy ( pvt ) ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & iflock ) ;
2003-03-31 07:13:36 +00:00
}
2006-09-19 17:07:22 +00:00
static int oh323_digit_begin ( struct ast_channel * c , char digit )
2006-08-31 01:59:02 +00:00
{
2006-09-19 17:07:22 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
char * token ;
if ( ! pvt ) {
ast_log ( LOG_ERROR , " No private structure?! This is bad \n " ) ;
return - 1 ;
}
ast_mutex_lock ( & pvt - > lock ) ;
2006-09-25 09:03:14 +00:00
if ( pvt - > rtp & &
( ( ( pvt - > options . dtmfmode & H323_DTMF_RFC2833 ) & & pvt - > dtmf_pt [ 0 ] )
/*|| ((pvt->options.dtmfmode & H323_DTMF_CISCO) && pvt->dtmf_pt[1]))*/ ) ) {
2006-09-19 17:07:22 +00:00
/* out-of-band DTMF */
if ( h323debug ) {
ast_log ( LOG_DTMF , " Begin sending out-of-band digit %c on %s \n " , digit , c - > name ) ;
}
ast_rtp_senddigit_begin ( pvt - > rtp , digit ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
} else if ( pvt - > txDtmfDigit ! = digit ) {
/* in-band DTMF */
if ( h323debug ) {
ast_log ( LOG_DTMF , " Begin sending inband digit %c on %s \n " , digit , c - > name ) ;
}
pvt - > txDtmfDigit = digit ;
2007-06-14 23:01:01 +00:00
token = pvt - > cd . call_token ? ast_strdup ( pvt - > cd . call_token ) : NULL ;
2006-09-19 17:07:22 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
h323_send_tone ( token , digit ) ;
if ( token ) {
2007-06-03 06:10:27 +00:00
ast_free ( token ) ;
2006-09-19 17:07:22 +00:00
}
} else
ast_mutex_unlock ( & pvt - > lock ) ;
oh323_update_info ( c ) ;
2006-08-31 01:59:02 +00:00
return 0 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief
2003-03-31 07:13:36 +00:00
* Send ( play ) the specified digit to the channel .
2006-09-19 17:07:22 +00:00
*
2003-03-31 07:13:36 +00:00
*/
Merged revisions 51311 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r51311 | russell | 2007-01-19 11:49:38 -0600 (Fri, 19 Jan 2007) | 23 lines
Merge the changes from the /team/group/vldtmf_fixup branch.
The main bug being addressed here is a problem introduced when two SIP
channels using SIP INFO dtmf have their media directly bridged. So, when a
DTMF END frame comes into Asterisk from an incoming INFO message, Asterisk
would try to emulate a digit of some length by first sending a DTMF BEGIN
frame and sending a DTMF END later timed off of incoming audio. However,
since there was no audio coming in, the DTMF_END was never generated. This
caused DTMF based features to no longer work.
To fix this, the core now knows when a channel doesn't care about DTMF BEGIN
frames (such as a SIP channel sending INFO dtmf). If this is the case, then
Asterisk will not emulate a digit of some length, and will instead just pass
through the single DTMF END event.
Channel drivers also now get passed the length of the digit to their digit_end
callback. This improves SIP INFO support even further by enabling us to put
the real digit duration in the INFO message instead of a hard coded 250ms.
Also, for an incoming INFO message, the duration is read from the frame and
passed into the core instead of just getting ignored.
(issue #8597, maybe others...)
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@51314 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2007-01-19 18:06:03 +00:00
static int oh323_digit_end ( struct ast_channel * c , char digit , unsigned int duration )
2003-03-31 07:13:36 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2005-04-29 04:22:47 +00:00
char * token ;
2005-09-15 03:26:02 +00:00
if ( ! pvt ) {
2005-09-15 17:08:52 +00:00
ast_log ( LOG_ERROR , " No private structure?! This is bad \n " ) ;
2005-04-04 15:54:34 +00:00
return - 1 ;
2005-09-15 03:26:02 +00:00
}
2005-05-11 13:27:49 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2006-09-25 09:03:14 +00:00
if ( pvt - > rtp & & ( pvt - > options . dtmfmode & H323_DTMF_RFC2833 ) & & ( ( pvt - > dtmf_pt [ 0 ] > 0 ) | | ( pvt - > dtmf_pt [ 0 ] > 0 ) ) ) {
2005-09-15 03:26:02 +00:00
/* out-of-band DTMF */
if ( h323debug ) {
2007-02-10 09:23:09 +00:00
ast_log ( LOG_DTMF , " End sending out-of-band digit %c on %s, duration %d \n " , digit , c - > name , duration ) ;
2005-09-15 03:26:02 +00:00
}
2006-09-19 17:07:22 +00:00
ast_rtp_senddigit_end ( pvt - > rtp , digit ) ;
2006-08-15 14:55:30 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-09-15 03:26:02 +00:00
} else {
/* in-band DTMF */
if ( h323debug ) {
2007-02-10 09:23:09 +00:00
ast_log ( LOG_DTMF , " End sending inband digit %c on %s, duration %d \n " , digit , c - > name , duration ) ;
2005-09-15 03:26:02 +00:00
}
2006-09-19 17:07:22 +00:00
pvt - > txDtmfDigit = ' ' ;
2007-06-14 23:01:01 +00:00
token = pvt - > cd . call_token ? ast_strdup ( pvt - > cd . call_token ) : NULL ;
2006-08-15 14:55:30 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2006-09-19 17:07:22 +00:00
h323_send_tone ( token , ' ' ) ;
2005-09-15 03:26:02 +00:00
if ( token ) {
2007-06-03 06:10:27 +00:00
ast_free ( token ) ;
2005-09-15 03:26:02 +00:00
}
2003-03-31 07:13:36 +00:00
}
2005-09-15 03:14:21 +00:00
oh323_update_info ( c ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief
2006-09-19 17:07:22 +00:00
* Make a call over the specified channel to the specified
2004-10-04 10:13:01 +00:00
* destination .
* Returns - 1 on error , 0 on success .
2003-03-31 07:13:36 +00:00
*/
static int oh323_call ( struct ast_channel * c , char * dest , int timeout )
2006-09-19 17:07:22 +00:00
{
2005-05-11 13:27:49 +00:00
int res = 0 ;
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2006-09-19 17:07:22 +00:00
const char * addr ;
2005-05-11 13:27:49 +00:00
char called_addr [ 1024 ] ;
if ( h323debug ) {
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Calling to %s on %s \n " , dest , c - > name ) ;
2005-05-11 13:27:49 +00:00
}
2005-04-04 15:54:34 +00:00
if ( ( c - > _state ! = AST_STATE_DOWN ) & & ( c - > _state ! = AST_STATE_RESERVED ) ) {
2005-05-11 13:27:49 +00:00
ast_log ( LOG_WARNING , " Line is already in use (%s) \n " , c - > name ) ;
return - 1 ;
}
ast_mutex_lock ( & pvt - > lock ) ;
2006-09-19 17:07:22 +00:00
if ( ! gatekeeper_disable ) {
2005-05-11 13:27:49 +00:00
if ( ast_strlen_zero ( pvt - > exten ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( called_addr , dest , sizeof ( called_addr ) ) ;
2005-05-11 13:27:49 +00:00
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s " , pvt - > exten , dest ) ;
}
} else {
res = htons ( pvt - > sa . sin_port ) ;
2006-09-19 17:07:22 +00:00
addr = ast_inet_ntoa ( pvt - > sa . sin_addr ) ;
2005-05-11 13:27:49 +00:00
if ( ast_strlen_zero ( pvt - > exten ) ) {
snprintf ( called_addr , sizeof ( called_addr ) , " %s:%d " , addr , res ) ;
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s:%d " , pvt - > exten , addr , res ) ;
2005-04-04 15:54:34 +00:00
}
2004-12-16 02:03:19 +00:00
}
2005-04-04 15:54:34 +00:00
/* make sure null terminated */
2006-09-19 17:07:22 +00:00
called_addr [ sizeof ( called_addr ) - 1 ] = ' \0 ' ;
2004-12-16 02:03:19 +00:00
2006-09-19 17:07:22 +00:00
if ( c - > cid . cid_num )
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > options . cid_num , c - > cid . cid_num , sizeof ( pvt - > options . cid_num ) ) ;
2006-09-19 17:07:22 +00:00
if ( c - > cid . cid_name )
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > options . cid_name , c - > cid . cid_name , sizeof ( pvt - > options . cid_name ) ) ;
2006-09-19 17:07:22 +00:00
if ( c - > cid . cid_rdnis ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > options . cid_rdnis , c - > cid . cid_rdnis , sizeof ( pvt - > options . cid_rdnis ) ) ;
2004-12-16 02:03:19 +00:00
}
2006-09-29 18:35:44 +00:00
pvt - > options . presentation = c - > cid . cid_pres ;
pvt - > options . type_of_number = c - > cid . cid_ton ;
2006-09-19 17:07:22 +00:00
if ( ( addr = pbx_builtin_getvar_helper ( c , " PRIREDIRECTREASON " ) ) ) {
if ( ! strcasecmp ( addr , " UNKNOWN " ) )
pvt - > options . redirect_reason = 0 ;
else if ( ! strcasecmp ( addr , " BUSY " ) )
pvt - > options . redirect_reason = 1 ;
else if ( ! strcasecmp ( addr , " NO_REPLY " ) )
pvt - > options . redirect_reason = 2 ;
else if ( ! strcasecmp ( addr , " UNCONDITIONAL " ) )
pvt - > options . redirect_reason = 15 ;
else
pvt - > options . redirect_reason = - 1 ;
} else
pvt - > options . redirect_reason = - 1 ;
2006-10-07 14:48:32 +00:00
pvt - > options . transfer_capability = c - > transfercapability ;
2004-11-11 21:30:30 +00:00
/* indicate that this is an outgoing call */
2004-10-04 10:13:01 +00:00
pvt - > outgoing = 1 ;
2004-11-11 21:30:30 +00:00
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , " Requested transfer capability: 0x%.2x - %s \n " , c - > transfercapability , ast_transfercapability2str ( c - > transfercapability ) ) ;
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Placing outgoing call to %s, %d/%d \n " , called_addr , pvt - > options . dtmfcodec [ 0 ] , pvt - > options . dtmfcodec [ 1 ] ) ;
2005-05-11 13:27:49 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-12-15 23:24:13 +00:00
res = h323_make_call ( called_addr , & ( pvt - > cd ) , & pvt - > options ) ;
2003-03-31 07:13:36 +00:00
if ( res ) {
2003-05-12 00:55:52 +00:00
ast_log ( LOG_NOTICE , " h323_make_call failed(%s) \n " , c - > name ) ;
2003-03-31 07:13:36 +00:00
return - 1 ;
}
2005-04-04 15:54:34 +00:00
oh323_update_info ( c ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
static int oh323_answer ( struct ast_channel * c )
{
int res ;
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2005-04-04 15:54:34 +00:00
char * token ;
2003-03-31 07:13:36 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Answering on %s \n " , c - > name ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2007-06-14 23:01:01 +00:00
token = pvt - > cd . call_token ? ast_strdup ( pvt - > cd . call_token ) : NULL ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
res = h323_answering_call ( token , 0 ) ;
if ( token )
2007-06-03 06:10:27 +00:00
ast_free ( token ) ;
2005-04-04 15:54:34 +00:00
oh323_update_info ( c ) ;
2004-10-28 06:06:58 +00:00
if ( c - > _state ! = AST_STATE_UP ) {
2003-03-31 07:13:36 +00:00
ast_setstate ( c , AST_STATE_UP ) ;
2004-10-28 06:06:58 +00:00
}
2003-03-31 07:13:36 +00:00
return res ;
}
static int oh323_hangup ( struct ast_channel * c )
{
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2004-12-16 04:25:49 +00:00
int q931cause = AST_CAUSE_NORMAL_CLEARING ;
2005-04-04 15:54:34 +00:00
char * call_token ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Hanging up and scheduling destroy of call %s \n " , c - > name ) ;
2004-12-16 04:25:49 +00:00
2005-03-04 06:47:24 +00:00
if ( ! c - > tech_pvt ) {
2006-09-19 17:07:22 +00:00
ast_log ( LOG_WARNING , " Asked to hangup channel not connected \n " ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
2004-10-04 10:13:01 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
/* Determine how to disconnect */
2004-10-04 10:13:01 +00:00
if ( pvt - > owner ! = c ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Huh? We aren't the owner? \n " ) ;
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
2006-09-19 17:07:22 +00:00
2004-10-04 10:13:01 +00:00
pvt - > owner = NULL ;
2005-03-04 06:47:24 +00:00
c - > tech_pvt = NULL ;
2003-03-31 07:13:36 +00:00
2004-12-16 04:25:49 +00:00
if ( c - > hangupcause ) {
q931cause = c - > hangupcause ;
} else {
2006-04-03 18:36:30 +00:00
const char * cause = pbx_builtin_getvar_helper ( c , " DIALSTATUS " ) ;
2004-12-16 04:25:49 +00:00
if ( cause ) {
if ( ! strcmp ( cause , " CONGESTION " ) ) {
q931cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION ;
} else if ( ! strcmp ( cause , " BUSY " ) ) {
q931cause = AST_CAUSE_USER_BUSY ;
} else if ( ! strcmp ( cause , " CHANISUNVAIL " ) ) {
q931cause = AST_CAUSE_REQUESTED_CHAN_UNAVAIL ;
} else if ( ! strcmp ( cause , " NOANSWER " ) ) {
q931cause = AST_CAUSE_NO_ANSWER ;
} else if ( ! strcmp ( cause , " CANCEL " ) ) {
q931cause = AST_CAUSE_CALL_REJECTED ;
}
}
}
2003-03-31 07:13:36 +00:00
/* Start the process if it's not already started */
2005-04-04 15:54:34 +00:00
if ( ! pvt - > alreadygone & & ! pvt - > hangupcause ) {
2007-06-14 23:01:01 +00:00
call_token = pvt - > cd . call_token ? ast_strdup ( pvt - > cd . call_token ) : NULL ;
2005-04-04 15:54:34 +00:00
if ( call_token ) {
/* Release lock to eliminate deadlock */
ast_mutex_unlock ( & pvt - > lock ) ;
2006-09-19 17:07:22 +00:00
if ( h323_clear_call ( call_token , q931cause ) ) {
ast_log ( LOG_WARNING , " ClearCall failed. \n " ) ;
2005-04-04 15:54:34 +00:00
}
2007-06-03 06:10:27 +00:00
ast_free ( call_token ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2004-01-06 16:51:34 +00:00
}
2006-09-19 17:07:22 +00:00
}
2005-04-04 15:54:34 +00:00
pvt - > needdestroy = 1 ;
2006-09-19 17:07:22 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
2003-04-23 21:52:46 +00:00
/* Update usage counter */
2006-09-19 17:07:22 +00:00
ast_module_unref ( ast_module_info - > self ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
2004-10-04 10:13:01 +00:00
static struct ast_frame * oh323_rtp_read ( struct oh323_pvt * pvt )
2003-03-31 07:13:36 +00:00
{
struct ast_frame * f ;
2003-09-22 06:21:03 +00:00
2005-05-21 17:09:30 +00:00
/* Only apply it for the first packet, we just need the correct ip/port */
if ( pvt - > options . nat ) {
ast_rtp_setnat ( pvt - > rtp , pvt - > options . nat ) ;
pvt - > options . nat = 0 ;
}
2003-09-22 06:21:03 +00:00
2004-10-04 10:13:01 +00:00
f = ast_rtp_read ( pvt - > rtp ) ;
2003-03-31 07:13:36 +00:00
/* Don't send RFC2833 if we're not supposed to */
2006-09-25 09:03:14 +00:00
if ( f & & ( f - > frametype = = AST_FRAME_DTMF ) & & ! ( pvt - > options . dtmfmode & ( H323_DTMF_RFC2833 | H323_DTMF_CISCO ) ) ) {
2006-01-31 17:18:58 +00:00
return & ast_null_frame ;
2004-10-28 06:06:58 +00:00
}
2004-10-04 10:13:01 +00:00
if ( pvt - > owner ) {
2003-03-31 07:13:36 +00:00
/* We already hold the channel lock */
if ( f - > frametype = = AST_FRAME_VOICE ) {
2004-10-04 10:13:01 +00:00
if ( f - > subclass ! = pvt - > owner - > nativeformats ) {
2005-04-04 15:54:34 +00:00
/* Try to avoid deadlock */
2006-09-19 17:07:22 +00:00
if ( ast_channel_trylock ( pvt - > owner ) ) {
2005-04-04 15:54:34 +00:00
ast_log ( LOG_NOTICE , " Format changed but channel is locked. Ignoring frame... \n " ) ;
2006-01-31 17:18:58 +00:00
return & ast_null_frame ;
2005-04-04 15:54:34 +00:00
}
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Oooh, format changed to %d \n " , f - > subclass ) ;
2004-10-04 10:13:01 +00:00
pvt - > owner - > nativeformats = f - > subclass ;
2005-04-04 15:54:34 +00:00
pvt - > nativeformats = f - > subclass ;
2004-10-04 10:13:01 +00:00
ast_set_read_format ( pvt - > owner , pvt - > owner - > readformat ) ;
ast_set_write_format ( pvt - > owner , pvt - > owner - > writeformat ) ;
2006-09-19 17:07:22 +00:00
ast_channel_unlock ( pvt - > owner ) ;
}
2003-03-31 07:13:36 +00:00
/* Do in-band DTMF detection */
2005-05-21 17:09:30 +00:00
if ( ( pvt - > options . dtmfmode & H323_DTMF_INBAND ) & & pvt - > vad ) {
2006-09-19 17:07:22 +00:00
if ( ( pvt - > nativeformats & ( AST_FORMAT_SLINEAR | AST_FORMAT_ALAW | AST_FORMAT_ULAW ) ) ) {
if ( ! ast_channel_trylock ( pvt - > owner ) ) {
f = ast_dsp_process ( pvt - > owner , pvt - > vad , f ) ;
ast_channel_unlock ( pvt - > owner ) ;
}
else
ast_log ( LOG_NOTICE , " Unable to process inband DTMF while channel is locked \n " ) ;
} else if ( pvt - > nativeformats & & ! pvt - > noInbandDtmf ) {
ast_log ( LOG_NOTICE , " Inband DTMF is not supported on codec %s. Use RFC2833 \n " , ast_getformatname ( f - > subclass ) ) ;
pvt - > noInbandDtmf = 1 ;
2005-07-27 04:45:11 +00:00
}
2005-02-13 07:45:40 +00:00
if ( f & & ( f - > frametype = = AST_FRAME_DTMF ) ) {
2006-09-19 17:07:22 +00:00
if ( h323debug )
ast_log ( LOG_DTMF , " Received in-band digit %c. \n " , f - > subclass ) ;
2005-07-27 04:45:11 +00:00
}
2004-10-04 10:13:01 +00:00
}
2003-03-31 07:13:36 +00:00
}
}
return f ;
}
2005-07-27 04:45:11 +00:00
static struct ast_frame * oh323_read ( struct ast_channel * c )
2003-03-31 07:13:36 +00:00
{
struct ast_frame * fr ;
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2004-10-04 10:13:01 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2005-05-11 13:27:49 +00:00
__oh323_update_info ( c , pvt ) ;
2006-09-19 17:07:22 +00:00
switch ( c - > fdno ) {
case 0 :
fr = oh323_rtp_read ( pvt ) ;
break ;
case 1 :
if ( pvt - > rtp )
fr = ast_rtcp_read ( pvt - > rtp ) ;
else
fr = & ast_null_frame ;
break ;
default :
ast_log ( LOG_ERROR , " Unable to handle fd %d on channel %s \n " , c - > fdno , c - > name ) ;
fr = & ast_null_frame ;
break ;
}
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
return fr ;
}
static int oh323_write ( struct ast_channel * c , struct ast_frame * frame )
{
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2003-03-31 07:13:36 +00:00
int res = 0 ;
if ( frame - > frametype ! = AST_FRAME_VOICE ) {
2004-10-28 06:06:58 +00:00
if ( frame - > frametype = = AST_FRAME_IMAGE ) {
2003-03-31 07:13:36 +00:00
return 0 ;
2004-10-28 06:06:58 +00:00
} else {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Can't send %d type frames with H323 write \n " , frame - > frametype ) ;
return 0 ;
}
} else {
if ( ! ( frame - > subclass & c - > nativeformats ) ) {
2003-12-24 22:38:24 +00:00
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 ) ;
2005-04-04 15:54:34 +00:00
return 0 ;
2003-03-31 07:13:36 +00:00
}
}
2004-10-04 10:13:01 +00:00
if ( pvt ) {
ast_mutex_lock ( & pvt - > lock ) ;
2006-09-19 17:07:22 +00:00
if ( pvt - > rtp & & ! pvt - > recvonly )
res = ast_rtp_write ( pvt - > rtp , frame ) ;
2005-07-27 04:45:11 +00:00
__oh323_update_info ( c , pvt ) ;
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
}
return res ;
}
2006-05-10 15:00:33 +00:00
static int oh323_indicate ( struct ast_channel * c , int condition , const void * data , size_t datalen )
2003-03-31 07:13:36 +00:00
{
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2005-04-04 15:54:34 +00:00
char * token = ( char * ) NULL ;
2006-10-01 19:40:00 +00:00
int res = - 1 ;
int got_progress ;
2004-12-15 23:24:13 +00:00
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2007-06-14 23:01:01 +00:00
token = ( pvt - > cd . call_token ? ast_strdup ( pvt - > cd . call_token ) : NULL ) ;
2006-10-01 19:40:00 +00:00
got_progress = pvt - > got_progress ;
if ( condition = = AST_CONTROL_PROGRESS )
pvt - > got_progress = 1 ;
2006-10-02 18:57:49 +00:00
else if ( ( condition = = AST_CONTROL_BUSY ) | | ( condition = = AST_CONTROL_CONGESTION ) )
pvt - > alreadygone = 1 ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " OH323: Indicating %d on %s (%s) \n " , condition , token , c - > name ) ;
2004-12-15 23:24:13 +00:00
2003-03-31 07:13:36 +00:00
switch ( condition ) {
case AST_CONTROL_RINGING :
2004-05-20 07:07:18 +00:00
if ( c - > _state = = AST_STATE_RING | | c - > _state = = AST_STATE_RINGING ) {
2005-04-04 15:54:34 +00:00
h323_send_alerting ( token ) ;
2006-10-01 19:40:00 +00:00
res = ( got_progress ? 0 : - 1 ) ; /* Do not simulate any audio tones if we got PROGRESS message */
2006-09-19 17:07:22 +00:00
}
2006-10-02 18:57:49 +00:00
break ;
2004-05-20 07:07:18 +00:00
case AST_CONTROL_PROGRESS :
if ( c - > _state ! = AST_STATE_UP ) {
2006-10-01 19:40:00 +00:00
/* Do not send PROGRESS message more than once */
if ( ! got_progress )
h323_send_progress ( token ) ;
2006-10-02 18:57:49 +00:00
res = 0 ;
2003-03-31 07:13:36 +00:00
}
2006-10-02 18:57:49 +00:00
break ;
2003-03-31 07:13:36 +00:00
case AST_CONTROL_BUSY :
if ( c - > _state ! = AST_STATE_UP ) {
2005-04-04 15:54:34 +00:00
h323_answering_call ( token , 1 ) ;
2006-09-19 17:07:22 +00:00
ast_softhangup_nolock ( c , AST_SOFTHANGUP_DEV ) ;
2006-10-02 18:57:49 +00:00
res = 0 ;
2003-03-31 07:13:36 +00:00
}
2006-10-02 18:57:49 +00:00
break ;
2003-03-31 07:13:36 +00:00
case AST_CONTROL_CONGESTION :
if ( c - > _state ! = AST_STATE_UP ) {
2005-04-04 15:54:34 +00:00
h323_answering_call ( token , 1 ) ;
2004-05-20 07:07:18 +00:00
ast_softhangup_nolock ( c , AST_SOFTHANGUP_DEV ) ;
2006-10-02 18:57:49 +00:00
res = 0 ;
2003-03-31 07:13:36 +00:00
}
2006-10-02 18:57:49 +00:00
break ;
2006-07-19 20:44:39 +00:00
case AST_CONTROL_HOLD :
2006-09-28 10:41:38 +00:00
h323_hold_call ( token , 1 ) ;
/* We should start MOH only if remote party isn't provide audio for us */
2006-07-19 20:44:39 +00:00
ast_moh_start ( c , data , NULL ) ;
2006-10-02 18:57:49 +00:00
res = 0 ;
break ;
2006-07-19 20:44:39 +00:00
case AST_CONTROL_UNHOLD :
2006-09-28 10:41:38 +00:00
h323_hold_call ( token , 0 ) ;
2006-07-19 20:44:39 +00:00
ast_moh_stop ( c ) ;
2006-10-02 18:57:49 +00:00
res = 0 ;
break ;
2008-03-05 22:43:22 +00:00
case AST_CONTROL_SRCUPDATE :
ast_rtp_new_source ( pvt - > rtp ) ;
res = 0 ;
break ;
2004-06-14 21:18:52 +00:00
case AST_CONTROL_PROCEEDING :
2003-03-31 07:13:36 +00:00
case - 1 :
2006-10-02 18:57:49 +00:00
break ;
2003-03-31 07:13:36 +00:00
default :
2006-10-02 18:57:49 +00:00
ast_log ( LOG_WARNING , " OH323: Don't know how to indicate condition %d on %s \n " , condition , token ) ;
break ;
2003-03-31 07:13:36 +00:00
}
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " OH323: Indicated %d on %s, res=%d \n " , condition , token , res ) ;
2005-04-04 15:54:34 +00:00
if ( token )
2007-06-03 06:10:27 +00:00
ast_free ( token ) ;
2005-04-04 15:54:34 +00:00
oh323_update_info ( c ) ;
2006-10-01 19:40:00 +00:00
return res ;
2003-03-31 07:13:36 +00:00
}
2004-04-08 19:19:24 +00:00
static int oh323_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan )
2003-03-31 07:13:36 +00:00
{
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) newchan - > tech_pvt ;
2003-03-31 07:13:36 +00:00
2004-10-04 10:13:01 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
if ( pvt - > owner ! = oldchan ) {
ast_log ( LOG_WARNING , " old channel wasn't %p but was %p \n " , oldchan , pvt - > owner ) ;
2003-03-31 07:13:36 +00:00
return - 1 ;
}
2004-10-04 10:13:01 +00:00
pvt - > owner = newchan ;
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
2006-09-19 17:07:22 +00:00
static int __oh323_rtp_create ( struct oh323_pvt * pvt )
{
struct in_addr our_addr ;
if ( pvt - > rtp )
return 0 ;
if ( ast_find_ourip ( & our_addr , bindaddr ) ) {
ast_mutex_unlock ( & pvt - > lock ) ;
ast_log ( LOG_ERROR , " Unable to locate local IP address for RTP stream \n " ) ;
return - 1 ;
}
pvt - > rtp = ast_rtp_new_with_bindaddr ( sched , io , 1 , 0 , our_addr ) ;
if ( ! pvt - > rtp ) {
ast_mutex_unlock ( & pvt - > lock ) ;
ast_log ( LOG_WARNING , " Unable to create RTP session: %s \n " , strerror ( errno ) ) ;
return - 1 ;
}
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Created RTP channel \n " ) ;
2006-09-19 17:07:22 +00:00
2007-12-16 10:51:53 +00:00
ast_rtp_setqos ( pvt - > rtp , tos , cos , " H323 RTP " ) ;
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Setting NAT on RTP to %d \n " , pvt - > options . nat ) ;
2006-09-19 17:07:22 +00:00
ast_rtp_setnat ( pvt - > rtp , pvt - > options . nat ) ;
2006-09-25 09:03:14 +00:00
if ( pvt - > dtmf_pt [ 0 ] > 0 )
ast_rtp_set_rtpmap_type ( pvt - > rtp , pvt - > dtmf_pt [ 0 ] , " audio " , " telephone-event " , 0 ) ;
if ( pvt - > dtmf_pt [ 1 ] > 0 )
ast_rtp_set_rtpmap_type ( pvt - > rtp , pvt - > dtmf_pt [ 1 ] , " audio " , " cisco-telephone-event " , 0 ) ;
2006-09-19 17:07:22 +00:00
2006-09-20 16:24:00 +00:00
if ( pvt - > peercapability )
ast_rtp_codec_setpref ( pvt - > rtp , & pvt - > peer_prefs ) ;
2006-09-19 17:07:22 +00:00
if ( pvt - > owner & & ! ast_channel_trylock ( pvt - > owner ) ) {
ast_jb_configure ( pvt - > owner , & global_jbconf ) ;
2007-08-08 21:44:58 +00:00
ast_channel_set_fd ( pvt - > owner , 0 , ast_rtp_fd ( pvt - > rtp ) ) ;
ast_channel_set_fd ( pvt - > owner , 1 , ast_rtcp_fd ( pvt - > rtp ) ) ;
2006-09-19 17:07:22 +00:00
ast_queue_frame ( pvt - > owner , & ast_null_frame ) ; /* Tell Asterisk to apply changes */
ast_channel_unlock ( pvt - > owner ) ;
} else
pvt - > update_rtp_info = 1 ;
return 0 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief Private structure should be locked on a call */
2005-05-11 13:27:49 +00:00
static struct ast_channel * __oh323_new ( struct oh323_pvt * pvt , int state , const char * host )
2003-03-31 07:13:36 +00:00
{
2003-08-16 17:00:22 +00:00
struct ast_channel * ch ;
2006-11-07 21:47:49 +00:00
char * cid_num , * cid_name ;
2003-03-31 07:13:36 +00:00
int fmt ;
2006-09-19 17:07:22 +00:00
2006-11-07 21:47:49 +00:00
if ( ! ast_strlen_zero ( pvt - > options . cid_num ) )
cid_num = pvt - > options . cid_num ;
else
cid_num = pvt - > cd . call_source_e164 ;
if ( ! ast_strlen_zero ( pvt - > options . cid_name ) )
cid_name = pvt - > options . cid_name ;
else
cid_name = pvt - > cd . call_source_name ;
2004-10-22 19:04:02 +00:00
/* Don't hold a oh323_pvt lock while we allocate a chanel */
ast_mutex_unlock ( & pvt - > lock ) ;
2007-04-10 05:41:34 +00:00
ch = ast_channel_alloc ( 1 , state , cid_num , cid_name , pvt - > accountcode , pvt - > exten , pvt - > context , pvt - > amaflags , " H323/%s " , host ) ;
2006-06-23 16:49:12 +00:00
/* Update usage counter */
2006-09-19 17:07:22 +00:00
ast_module_ref ( ast_module_info - > self ) ;
2004-10-22 19:04:02 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2003-08-16 17:00:22 +00:00
if ( ch ) {
2005-03-08 23:11:23 +00:00
ch - > tech = & oh323_tech ;
2006-09-19 17:07:22 +00:00
if ( ! ( fmt = pvt - > jointcapability ) & & ! ( fmt = pvt - > options . capability ) )
fmt = global_options . capability ;
ch - > nativeformats = ast_codec_choose ( & pvt - > options . prefs , fmt , 1 ) /* | (pvt->jointcapability & AST_FORMAT_VIDEO_MASK)*/ ;
2005-04-04 15:54:34 +00:00
pvt - > nativeformats = ch - > nativeformats ;
2003-08-16 17:00:22 +00:00
fmt = ast_best_codec ( ch - > nativeformats ) ;
ch - > writeformat = fmt ;
2005-03-04 06:47:24 +00:00
ch - > rawwriteformat = fmt ;
2003-08-16 17:00:22 +00:00
ch - > readformat = fmt ;
2005-03-04 06:47:24 +00:00
ch - > rawreadformat = fmt ;
2008-01-23 15:23:51 +00:00
if ( ! pvt - > rtp )
__oh323_rtp_create ( pvt ) ;
2006-09-19 17:07:22 +00:00
#if 0
2007-08-08 21:44:58 +00:00
ast_channel_set_fd ( ch , 0 , ast_rtp_fd ( pvt - > rtp ) ) ;
ast_channel_set_fd ( ch , 1 , ast_rtcp_fd ( pvt - > rtp ) ) ;
2006-09-19 17:07:22 +00:00
# endif
# ifdef VIDEO_SUPPORT
if ( pvt - > vrtp ) {
2007-08-08 21:44:58 +00:00
ast_channel_set_fd ( ch , 2 , ast_rtp_fd ( pvt - > vrtp ) ) ;
ast_channel_set_fd ( ch , 3 , ast_rtcp_fd ( pvt - > vrtp ) ) ;
2006-09-19 17:07:22 +00:00
}
# endif
# ifdef T38_SUPPORT
if ( pvt - > udptl ) {
2007-08-08 21:44:58 +00:00
ast_channel_set_fd ( ch , 4 , ast_udptl_fd ( pvt - > udptl ) ) ;
2006-09-19 17:07:22 +00:00
}
# endif
if ( state = = AST_STATE_RING ) {
ch - > rings = 1 ;
}
2003-03-31 07:13:36 +00:00
/* Allocate dsp for in-band DTMF support */
2005-05-21 17:09:30 +00:00
if ( pvt - > options . dtmfmode & H323_DTMF_INBAND ) {
2004-10-04 10:13:01 +00:00
pvt - > vad = ast_dsp_new ( ) ;
2008-03-19 22:25:34 +00:00
ast_dsp_set_features ( pvt - > vad , DSP_FEATURE_DIGIT_DETECT ) ;
2006-09-19 17:07:22 +00:00
}
2004-10-22 19:04:02 +00:00
/* Register channel functions. */
2005-03-04 06:47:24 +00:00
ch - > tech_pvt = pvt ;
2006-09-19 17:07:22 +00:00
/* Set the owner of this channel */
2004-10-04 10:13:01 +00:00
pvt - > owner = ch ;
2006-09-19 17:07:22 +00:00
2006-10-25 14:44:50 +00:00
ast_copy_string ( ch - > context , pvt - > context , sizeof ( ch - > context ) ) ;
ast_copy_string ( ch - > exten , pvt - > exten , sizeof ( ch - > exten ) ) ;
2003-08-16 17:00:22 +00:00
ch - > priority = 1 ;
2004-10-22 19:04:02 +00:00
if ( ! ast_strlen_zero ( pvt - > accountcode ) ) {
2006-04-03 18:36:30 +00:00
ast_string_field_set ( ch , accountcode , pvt - > accountcode ) ;
2004-10-22 19:04:02 +00:00
}
if ( pvt - > amaflags ) {
2004-10-04 10:13:01 +00:00
ch - > amaflags = pvt - > amaflags ;
2004-10-22 19:04:02 +00:00
}
2006-09-19 17:07:22 +00:00
2006-08-05 05:26:29 +00:00
/* Don't use ast_set_callerid() here because it will
2006-11-07 21:47:49 +00:00
* generate a needless NewCallerID event */
ch - > cid . cid_ani = ast_strdup ( cid_num ) ;
2006-09-19 17:07:22 +00:00
if ( pvt - > cd . redirect_reason > = 0 ) {
ch - > cid . cid_rdnis = ast_strdup ( pvt - > cd . redirect_number ) ;
pbx_builtin_setvar_helper ( ch , " PRIREDIRECTREASON " , redirectingreason2str ( pvt - > cd . redirect_reason ) ) ;
}
2006-09-29 18:35:44 +00:00
ch - > cid . cid_pres = pvt - > cd . presentation ;
ch - > cid . cid_ton = pvt - > cd . type_of_number ;
2006-09-19 17:07:22 +00:00
2004-10-22 19:04:02 +00:00
if ( ! ast_strlen_zero ( pvt - > exten ) & & strcmp ( pvt - > exten , " s " ) ) {
2007-06-14 23:01:01 +00:00
ch - > cid . cid_dnid = ast_strdup ( pvt - > exten ) ;
2004-10-22 19:04:02 +00:00
}
2006-10-07 14:48:32 +00:00
if ( pvt - > cd . transfer_capability > = 0 )
ch - > transfercapability = pvt - > cd . transfer_capability ;
2003-03-31 07:13:36 +00:00
if ( state ! = AST_STATE_DOWN ) {
2003-08-16 17:00:22 +00:00
if ( ast_pbx_start ( ch ) ) {
ast_log ( LOG_WARNING , " Unable to start PBX on %s \n " , ch - > name ) ;
ast_hangup ( ch ) ;
2006-06-23 16:49:12 +00:00
ch = NULL ;
2003-03-31 07:13:36 +00:00
}
}
2006-09-19 17:07:22 +00:00
} else {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Unable to allocate channel structure \n " ) ;
2004-10-22 19:04:02 +00:00
}
2003-08-16 17:00:22 +00:00
return ch ;
2003-03-31 07:13:36 +00:00
}
static struct oh323_pvt * oh323_alloc ( int callid )
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
2007-06-03 06:10:27 +00:00
pvt = ast_calloc ( 1 , sizeof ( * pvt ) ) ;
2004-10-04 10:13:01 +00:00
if ( ! pvt ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Couldn't allocate private structure. This is bad \n " ) ;
return NULL ;
}
2006-09-19 17:07:22 +00:00
pvt - > cd . redirect_reason = - 1 ;
2006-10-07 14:48:32 +00:00
pvt - > cd . transfer_capability = - 1 ;
2006-09-19 17:07:22 +00:00
/* Ensure the call token is allocated for outgoing call */
if ( ! callid ) {
if ( ( pvt - > cd ) . call_token = = NULL ) {
2007-06-03 06:10:27 +00:00
( pvt - > cd ) . call_token = ast_calloc ( 1 , 128 ) ;
2006-09-19 17:07:22 +00:00
}
if ( ! pvt - > cd . call_token ) {
ast_log ( LOG_ERROR , " Not enough memory to alocate call token \n " ) ;
ast_rtp_destroy ( pvt - > rtp ) ;
2007-06-03 06:10:27 +00:00
ast_free ( pvt ) ;
2006-09-19 17:07:22 +00:00
return NULL ;
}
memset ( ( char * ) ( pvt - > cd ) . call_token , 0 , 128 ) ;
pvt - > cd . call_reference = callid ;
2004-10-01 04:50:34 +00:00
}
2005-05-21 17:09:30 +00:00
memcpy ( & pvt - > options , & global_options , sizeof ( pvt - > options ) ) ;
2006-09-19 17:07:22 +00:00
pvt - > jointcapability = pvt - > options . capability ;
2006-09-25 09:03:14 +00:00
if ( pvt - > options . dtmfmode & ( H323_DTMF_RFC2833 | H323_DTMF_CISCO ) ) {
2004-10-04 10:13:01 +00:00
pvt - > nonCodecCapability | = AST_RTP_DTMF ;
2005-05-21 17:09:30 +00:00
} else {
pvt - > nonCodecCapability & = ~ AST_RTP_DTMF ;
2004-10-01 04:50:34 +00:00
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > context , default_context , sizeof ( pvt - > context ) ) ;
2006-09-19 17:07:22 +00:00
pvt - > newstate = pvt - > newcontrol = pvt - > newdigit = pvt - > update_rtp_info = pvt - > DTMFsched = - 1 ;
ast_mutex_init ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
/* Add to interface list */
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & iflock ) ;
2004-10-04 10:13:01 +00:00
pvt - > next = iflist ;
iflist = pvt ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & iflock ) ;
2004-10-04 10:13:01 +00:00
return pvt ;
2003-03-31 07:13:36 +00:00
}
2005-05-11 13:27:49 +00:00
static struct oh323_pvt * find_call_locked ( int call_reference , const char * token )
2006-09-19 17:07:22 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
2004-10-01 04:50:34 +00:00
ast_mutex_lock ( & iflock ) ;
2006-09-19 17:07:22 +00:00
pvt = iflist ;
2005-05-11 13:27:49 +00:00
while ( pvt ) {
if ( ! pvt - > needdestroy & & ( ( signed int ) pvt - > cd . call_reference = = call_reference ) ) {
2006-09-19 17:07:22 +00:00
/* Found the call */
2008-04-14 18:34:17 +00:00
if ( ( token ! = NULL ) & & ( pvt - > cd . call_token ! = NULL ) & & ( ! strcmp ( pvt - > cd . call_token , token ) ) ) {
2005-05-11 13:27:49 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
ast_mutex_unlock ( & iflock ) ;
return pvt ;
} else if ( token = = NULL ) {
ast_log ( LOG_WARNING , " Call Token is NULL \n " ) ;
ast_mutex_lock ( & pvt - > lock ) ;
ast_mutex_unlock ( & iflock ) ;
return pvt ;
}
}
2006-09-19 17:07:22 +00:00
pvt = pvt - > next ;
2005-05-11 13:27:49 +00:00
}
ast_mutex_unlock ( & iflock ) ;
2004-09-19 16:53:01 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2005-07-27 04:45:11 +00:00
static int update_state ( struct oh323_pvt * pvt , int state , int signal )
{
if ( ! pvt )
return 0 ;
2006-09-19 17:07:22 +00:00
if ( pvt - > owner & & ! ast_channel_trylock ( pvt - > owner ) ) {
2005-07-27 04:45:11 +00:00
if ( state > = 0 )
ast_setstate ( pvt - > owner , state ) ;
if ( signal > = 0 )
ast_queue_control ( pvt - > owner , signal ) ;
2006-09-19 17:07:22 +00:00
ast_channel_unlock ( pvt - > owner ) ;
2005-07-27 04:45:11 +00:00
return 1 ;
}
else {
if ( state > = 0 )
pvt - > newstate = state ;
if ( signal > = 0 )
2005-08-02 03:25:28 +00:00
pvt - > newcontrol = signal ;
2005-07-27 04:45:11 +00:00
return 0 ;
}
}
2006-09-19 17:07:22 +00:00
static struct oh323_alias * build_alias ( const char * name , struct ast_variable * v , struct ast_variable * alt , int realtime )
2004-10-04 10:13:01 +00:00
{
2006-09-19 17:07:22 +00:00
struct oh323_alias * alias ;
int found = 0 ;
alias = ASTOBJ_CONTAINER_FIND_UNLINK_FULL ( & aliasl , name , name , 0 , 0 , strcasecmp ) ;
if ( alias )
found + + ;
else {
2007-06-03 06:10:27 +00:00
if ( ! ( alias = ast_calloc ( 1 , sizeof ( * alias ) ) ) )
2006-09-19 17:07:22 +00:00
return NULL ;
ASTOBJ_INIT ( alias ) ;
}
if ( ! found & & name )
2006-10-25 14:44:50 +00:00
ast_copy_string ( alias - > name , name , sizeof ( alias - > name ) ) ;
2006-09-19 17:07:22 +00:00
for ( ; v | | ( ( v = alt ) & & ! ( alt = NULL ) ) ; v = v - > next ) {
if ( ! strcasecmp ( v - > name , " e164 " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( alias - > e164 , v - > value , sizeof ( alias - > e164 ) ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " prefix " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( alias - > prefix , v - > value , sizeof ( alias - > prefix ) ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " context " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( alias - > context , v - > value , sizeof ( alias - > context ) ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " secret " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( alias - > secret , v - > value , sizeof ( alias - > secret ) ) ;
2006-09-19 17:07:22 +00:00
} else {
if ( strcasecmp ( v - > value , " h323 " ) ) {
ast_log ( LOG_WARNING , " Keyword %s does not make sense in type=h323 \n " , v - > name ) ;
2004-10-04 10:13:01 +00:00
}
}
}
2006-09-19 17:07:22 +00:00
ASTOBJ_UNMARK ( alias ) ;
return alias ;
2004-10-04 10:13:01 +00:00
}
2006-09-19 17:07:22 +00:00
static struct oh323_alias * realtime_alias ( const char * alias )
2004-10-04 10:13:01 +00:00
{
2006-09-19 17:07:22 +00:00
struct ast_variable * var , * tmp ;
struct oh323_alias * a ;
2004-10-04 10:13:01 +00:00
2006-09-19 17:07:22 +00:00
var = ast_load_realtime ( " h323 " , " name " , alias , NULL ) ;
if ( ! var )
return NULL ;
for ( tmp = var ; tmp ; tmp = tmp - > next ) {
if ( ! strcasecmp ( tmp - > name , " type " ) & &
! ( ! strcasecmp ( tmp - > value , " alias " ) | | ! strcasecmp ( tmp - > value , " h323 " ) ) ) {
ast_variables_destroy ( var ) ;
return NULL ;
2004-10-04 10:13:01 +00:00
}
}
2006-09-19 17:07:22 +00:00
a = build_alias ( alias , var , NULL , 1 ) ;
ast_variables_destroy ( var ) ;
return a ;
2004-10-04 10:13:01 +00:00
}
2006-09-19 17:07:22 +00:00
static int update_common_options ( struct ast_variable * v , struct call_options * options )
2003-03-31 07:13:36 +00:00
{
2008-11-02 18:52:13 +00:00
int tmp = 0 ;
2006-09-24 18:59:38 +00:00
char * val , * opt ;
2004-09-30 19:36:46 +00:00
2006-09-19 17:07:22 +00:00
if ( ! strcasecmp ( v - > name , " allow " ) ) {
ast_parse_allow_disallow ( & options - > prefs , & options - > capability , v - > value , 1 ) ;
} else if ( ! strcasecmp ( v - > name , " disallow " ) ) {
ast_parse_allow_disallow ( & options - > prefs , & options - > capability , v - > value , 0 ) ;
} else if ( ! strcasecmp ( v - > name , " dtmfmode " ) ) {
2006-09-27 12:32:06 +00:00
val = ast_strdupa ( v - > value ) ;
2006-09-24 18:59:38 +00:00
if ( ( opt = strchr ( val , ' : ' ) ) ! = ( char * ) NULL ) {
* opt + + = ' \0 ' ;
tmp = atoi ( opt ) ;
}
2006-09-19 17:07:22 +00:00
if ( ! strcasecmp ( v - > value , " inband " ) ) {
2006-09-24 18:53:44 +00:00
options - > dtmfmode | = H323_DTMF_INBAND ;
2006-09-24 18:59:38 +00:00
} else if ( ! strcasecmp ( val , " rfc2833 " ) ) {
2006-09-24 18:53:44 +00:00
options - > dtmfmode | = H323_DTMF_RFC2833 ;
2006-09-25 09:03:14 +00:00
if ( ! opt ) {
options - > dtmfcodec [ 0 ] = H323_DTMF_RFC2833_PT ;
} else if ( ( tmp > = 96 ) & & ( tmp < 128 ) ) {
options - > dtmfcodec [ 0 ] = tmp ;
} else {
options - > dtmfcodec [ 0 ] = H323_DTMF_RFC2833_PT ;
ast_log ( LOG_WARNING , " Unknown rfc2833 payload %s specified at line %d, using default %d \n " , opt , v - > lineno , options - > dtmfcodec [ 0 ] ) ;
}
} else if ( ! strcasecmp ( val , " cisco " ) ) {
options - > dtmfmode | = H323_DTMF_CISCO ;
if ( ! opt ) {
options - > dtmfcodec [ 1 ] = H323_DTMF_CISCO_PT ;
} else if ( ( tmp > = 96 ) & & ( tmp < 128 ) ) {
options - > dtmfcodec [ 1 ] = tmp ;
} else {
options - > dtmfcodec [ 1 ] = H323_DTMF_CISCO_PT ;
ast_log ( LOG_WARNING , " Unknown Cisco DTMF payload %s specified at line %d, using default %d \n " , opt , v - > lineno , options - > dtmfcodec [ 1 ] ) ;
2006-09-24 18:59:38 +00:00
}
2006-09-25 09:03:14 +00:00
} else if ( ! strcasecmp ( v - > value , " h245-signal " ) ) {
options - > dtmfmode | = H323_DTMF_SIGNAL ;
2006-09-19 17:07:22 +00:00
} else {
2006-09-25 09:03:14 +00:00
ast_log ( LOG_WARNING , " Unknown dtmf mode '%s' at line %d \n " , v - > value , v - > lineno ) ;
2004-09-30 19:36:46 +00:00
}
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " dtmfcodec " ) ) {
2006-09-24 18:59:38 +00:00
ast_log ( LOG_NOTICE , " Option %s at line %d is deprecated. Use dtmfmode=rfc2833[:<payload>] instead. \n " , v - > name , v - > lineno ) ;
2006-09-19 17:07:22 +00:00
tmp = atoi ( v - > value ) ;
if ( tmp < 96 )
ast_log ( LOG_WARNING , " Invalid %s value %s at line %d \n " , v - > name , v - > value , v - > lineno ) ;
else
2006-09-25 09:03:14 +00:00
options - > dtmfcodec [ 0 ] = tmp ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " bridge " ) ) {
options - > bridge = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " nat " ) ) {
options - > nat = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " fastStart " ) ) {
options - > fastStart = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " h245Tunneling " ) ) {
options - > h245Tunneling = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " silenceSuppression " ) ) {
options - > silenceSuppression = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " progress_setup " ) ) {
tmp = atoi ( v - > value ) ;
if ( ( tmp ! = 0 ) & & ( tmp ! = 1 ) & & ( tmp ! = 3 ) & & ( tmp ! = 8 ) ) {
ast_log ( LOG_WARNING , " Invalid value %s for %s at line %d, assuming 0 \n " , v - > value , v - > name , v - > lineno ) ;
tmp = 0 ;
}
options - > progress_setup = tmp ;
} else if ( ! strcasecmp ( v - > name , " progress_alert " ) ) {
tmp = atoi ( v - > value ) ;
if ( ( tmp ! = 0 ) & & ( tmp ! = 1 ) & & ( tmp ! = 8 ) ) {
ast_log ( LOG_WARNING , " Invalid value %s for %s at line %d, assuming 0 \n " , v - > value , v - > name , v - > lineno ) ;
tmp = 0 ;
}
options - > progress_alert = tmp ;
} else if ( ! strcasecmp ( v - > name , " progress_audio " ) ) {
options - > progress_audio = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " callerid " ) ) {
ast_callerid_split ( v - > value , options - > cid_name , sizeof ( options - > cid_name ) , options - > cid_num , sizeof ( options - > cid_num ) ) ;
} else if ( ! strcasecmp ( v - > name , " fullname " ) ) {
ast_copy_string ( options - > cid_name , v - > value , sizeof ( options - > cid_name ) ) ;
} else if ( ! strcasecmp ( v - > name , " cid_number " ) ) {
ast_copy_string ( options - > cid_num , v - > value , sizeof ( options - > cid_num ) ) ;
} else if ( ! strcasecmp ( v - > name , " tunneling " ) ) {
if ( ! strcasecmp ( v - > value , " none " ) )
options - > tunnelOptions = 0 ;
else if ( ! strcasecmp ( v - > value , " cisco " ) )
options - > tunnelOptions | = H323_TUNNEL_CISCO ;
else if ( ! strcasecmp ( v - > value , " qsig " ) )
options - > tunnelOptions | = H323_TUNNEL_QSIG ;
else
ast_log ( LOG_WARNING , " Invalid value %s for %s at line %d \n " , v - > value , v - > name , v - > lineno ) ;
2006-09-28 10:41:38 +00:00
} else if ( ! strcasecmp ( v - > name , " hold " ) ) {
if ( ! strcasecmp ( v - > value , " none " ) )
options - > holdHandling = ~ 0 ;
else if ( ! strcasecmp ( v - > value , " notify " ) )
options - > holdHandling | = H323_HOLD_NOTIFY ;
else if ( ! strcasecmp ( v - > value , " q931only " ) )
options - > holdHandling | = H323_HOLD_NOTIFY | H323_HOLD_Q931ONLY ;
else if ( ! strcasecmp ( v - > value , " h450 " ) )
options - > holdHandling | = H323_HOLD_H450 ;
else
ast_log ( LOG_WARNING , " Invalid value %s for %s at line %d \n " , v - > value , v - > name , v - > lineno ) ;
2006-09-19 17:07:22 +00:00
} else
return 1 ;
return 0 ;
}
2007-11-15 15:21:04 +00:00
static struct oh323_user * build_user ( const char * name , struct ast_variable * v , struct ast_variable * alt , int realtime )
2006-09-19 17:07:22 +00:00
{
struct oh323_user * user ;
struct ast_ha * oldha ;
int found = 0 ;
int format ;
user = ASTOBJ_CONTAINER_FIND_UNLINK_FULL ( & userl , name , name , 0 , 0 , strcmp ) ;
if ( user )
found + + ;
else {
2007-06-03 06:10:27 +00:00
if ( ! ( user = ast_calloc ( 1 , sizeof ( * user ) ) ) )
2006-09-19 17:07:22 +00:00
return NULL ;
ASTOBJ_INIT ( user ) ;
}
oldha = user - > ha ;
user - > ha = ( struct ast_ha * ) NULL ;
memcpy ( & user - > options , & global_options , sizeof ( user - > options ) ) ;
2006-09-24 18:53:44 +00:00
user - > options . dtmfmode = 0 ;
2006-09-28 10:41:38 +00:00
user - > options . holdHandling = 0 ;
2006-09-19 17:07:22 +00:00
/* Set default context */
2006-10-25 14:44:50 +00:00
ast_copy_string ( user - > context , default_context , sizeof ( user - > context ) ) ;
2006-09-19 17:07:22 +00:00
if ( user & & ! found )
2006-10-25 14:44:50 +00:00
ast_copy_string ( user - > name , name , sizeof ( user - > name ) ) ;
2006-09-19 17:07:22 +00:00
#if 0 /* XXX Port channel variables functionality from chan_sip XXX */
if ( user - > chanvars ) {
ast_variables_destroy ( user - > chanvars ) ;
user - > chanvars = NULL ;
}
# endif
for ( ; v | | ( ( v = alt ) & & ! ( alt = NULL ) ) ; v = v - > next ) {
if ( ! update_common_options ( v , & user - > options ) )
continue ;
if ( ! strcasecmp ( v - > name , " context " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( user - > context , v - > value , sizeof ( user - > context ) ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " secret " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( user - > secret , v - > value , sizeof ( user - > secret ) ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " accountcode " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( user - > accountcode , v - > value , sizeof ( user - > accountcode ) ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " host " ) ) {
if ( ! strcasecmp ( v - > value , " dynamic " ) ) {
ast_log ( LOG_ERROR , " A dynamic host on a type=user does not make any sense \n " ) ;
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
return NULL ;
} else if ( ast_get_ip ( & user - > addr , v - > value ) ) {
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
return NULL ;
}
/* Let us know we need to use ip authentication */
user - > host = 1 ;
} else if ( ! strcasecmp ( v - > name , " amaflags " ) ) {
format = ast_cdr_amaflags2int ( v - > value ) ;
if ( format < 0 ) {
ast_log ( LOG_WARNING , " Invalid AMA Flags: %s at line %d \n " , v - > value , v - > lineno ) ;
} else {
user - > amaflags = format ;
}
} else if ( ! strcasecmp ( v - > name , " permit " ) | |
! strcasecmp ( v - > name , " deny " ) ) {
2007-01-18 06:59:22 +00:00
int ha_error = 0 ;
user - > ha = ast_append_ha ( v - > name , v - > value , user - > ha , & ha_error ) ;
if ( ha_error )
ast_log ( LOG_ERROR , " Bad ACL entry in configuration line %d : %s \n " , v - > lineno , v - > value ) ;
2006-09-19 17:07:22 +00:00
}
}
2006-09-24 18:53:44 +00:00
if ( ! user - > options . dtmfmode )
user - > options . dtmfmode = global_options . dtmfmode ;
2006-09-28 10:41:38 +00:00
if ( user - > options . holdHandling = = ~ 0 )
user - > options . holdHandling = 0 ;
else if ( ! user - > options . holdHandling )
user - > options . holdHandling = global_options . holdHandling ;
2006-09-19 17:07:22 +00:00
ASTOBJ_UNMARK ( user ) ;
ast_free_ha ( oldha ) ;
return user ;
}
static struct oh323_user * realtime_user ( const call_details_t * cd )
{
struct ast_variable * var , * tmp ;
struct oh323_user * user ;
2007-11-15 15:21:04 +00:00
const char * username ;
2006-09-19 17:07:22 +00:00
if ( userbyalias )
var = ast_load_realtime ( " h323 " , " name " , username = cd - > call_source_aliases , NULL ) ;
else {
username = ( char * ) NULL ;
var = ast_load_realtime ( " h323 " , " host " , cd - > sourceIp , NULL ) ;
}
if ( ! var )
return NULL ;
for ( tmp = var ; tmp ; tmp = tmp - > next ) {
if ( ! strcasecmp ( tmp - > name , " type " ) & &
! ( ! strcasecmp ( tmp - > value , " user " ) | | ! strcasecmp ( tmp - > value , " friend " ) ) ) {
ast_variables_destroy ( var ) ;
return NULL ;
} else if ( ! username & & ! strcasecmp ( tmp - > name , " name " ) )
username = tmp - > value ;
}
if ( ! username ) {
ast_log ( LOG_WARNING , " Cannot determine user name for IP address %s \n " , cd - > sourceIp ) ;
ast_variables_destroy ( var ) ;
return NULL ;
}
user = build_user ( username , var , NULL , 1 ) ;
ast_variables_destroy ( var ) ;
return user ;
}
static struct oh323_peer * build_peer ( const char * name , struct ast_variable * v , struct ast_variable * alt , int realtime )
{
struct oh323_peer * peer ;
struct ast_ha * oldha ;
int found = 0 ;
peer = ASTOBJ_CONTAINER_FIND_UNLINK_FULL ( & peerl , name , name , 0 , 0 , strcmp ) ;
if ( peer )
found + + ;
else {
2007-06-03 06:10:27 +00:00
if ( ! ( peer = ast_calloc ( 1 , sizeof ( * peer ) ) ) )
2006-09-19 17:07:22 +00:00
return NULL ;
ASTOBJ_INIT ( peer ) ;
}
oldha = peer - > ha ;
peer - > ha = NULL ;
memcpy ( & peer - > options , & global_options , sizeof ( peer - > options ) ) ;
2006-09-24 18:53:44 +00:00
peer - > options . dtmfmode = 0 ;
2006-09-28 10:41:38 +00:00
peer - > options . holdHandling = 0 ;
2006-09-19 17:07:22 +00:00
peer - > addr . sin_port = htons ( h323_signalling_port ) ;
peer - > addr . sin_family = AF_INET ;
if ( ! found & & name )
2006-10-25 14:44:50 +00:00
ast_copy_string ( peer - > name , name , sizeof ( peer - > name ) ) ;
2006-09-19 17:07:22 +00:00
#if 0 /* XXX Port channel variables functionality from chan_sip XXX */
if ( peer - > chanvars ) {
ast_variables_destroy ( peer - > chanvars ) ;
peer - > chanvars = NULL ;
}
# endif
/* Default settings for mailbox */
peer - > mailbox [ 0 ] = ' \0 ' ;
for ( ; v | | ( ( v = alt ) & & ! ( alt = NULL ) ) ; v = v - > next ) {
if ( ! update_common_options ( v , & peer - > options ) )
continue ;
if ( ! strcasecmp ( v - > name , " host " ) ) {
if ( ! strcasecmp ( v - > value , " dynamic " ) ) {
ast_log ( LOG_ERROR , " Dynamic host configuration not implemented. \n " ) ;
ASTOBJ_UNREF ( peer , oh323_destroy_peer ) ;
return NULL ;
}
if ( ast_get_ip ( & peer - > addr , v - > value ) ) {
ast_log ( LOG_ERROR , " Could not determine IP for %s \n " , v - > value ) ;
ASTOBJ_UNREF ( peer , oh323_destroy_peer ) ;
return NULL ;
}
} else if ( ! strcasecmp ( v - > name , " port " ) ) {
peer - > addr . sin_port = htons ( atoi ( v - > value ) ) ;
} else if ( ! strcasecmp ( v - > name , " permit " ) | |
! strcasecmp ( v - > name , " deny " ) ) {
2007-01-18 06:59:22 +00:00
int ha_error = 0 ;
peer - > ha = ast_append_ha ( v - > name , v - > value , peer - > ha , & ha_error ) ;
if ( ha_error )
ast_log ( LOG_ERROR , " Bad ACL entry in configuration line %d : %s \n " , v - > lineno , v - > value ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " mailbox " ) ) {
ast_copy_string ( peer - > mailbox , v - > value , sizeof ( peer - > mailbox ) ) ;
2008-06-16 19:57:05 +00:00
} else if ( ! strcasecmp ( v - > name , " hasvoicemail " ) ) {
if ( ast_true ( v - > value ) & & ast_strlen_zero ( peer - > mailbox ) ) {
ast_copy_string ( peer - > mailbox , name , sizeof ( peer - > mailbox ) ) ;
}
2006-09-19 17:07:22 +00:00
}
}
2006-09-24 18:53:44 +00:00
if ( ! peer - > options . dtmfmode )
peer - > options . dtmfmode = global_options . dtmfmode ;
2006-09-28 10:41:38 +00:00
if ( peer - > options . holdHandling = = ~ 0 )
peer - > options . holdHandling = 0 ;
else if ( ! peer - > options . holdHandling )
peer - > options . holdHandling = global_options . holdHandling ;
2006-09-19 17:07:22 +00:00
ASTOBJ_UNMARK ( peer ) ;
ast_free_ha ( oldha ) ;
return peer ;
}
static struct oh323_peer * realtime_peer ( const char * peername , struct sockaddr_in * sin )
{
struct oh323_peer * peer ;
struct ast_variable * var ;
struct ast_variable * tmp ;
2008-05-07 18:24:51 +00:00
const char * addr = NULL ;
2006-09-19 17:07:22 +00:00
/* First check on peer name */
if ( peername )
2008-05-07 18:24:51 +00:00
var = ast_load_realtime ( " h323 " , " name " , peername , NULL ) ;
2006-09-19 17:07:22 +00:00
else if ( sin ) /* Then check on IP address for dynamic peers */
var = ast_load_realtime ( " h323 " , " host " , addr = ast_inet_ntoa ( sin - > sin_addr ) , NULL ) ;
else
return NULL ;
if ( ! var )
return NULL ;
for ( tmp = var ; tmp ; tmp = tmp - > next ) {
/* If this is type=user, then skip this object. */
if ( ! strcasecmp ( tmp - > name , " type " ) & &
! ( ! strcasecmp ( tmp - > value , " peer " ) | | ! strcasecmp ( tmp - > value , " friend " ) ) ) {
ast_variables_destroy ( var ) ;
return NULL ;
} else if ( ! peername & & ! strcasecmp ( tmp - > name , " name " ) ) {
peername = tmp - > value ;
}
}
if ( ! peername ) { /* Did not find peer in realtime */
ast_log ( LOG_WARNING , " Cannot determine peer name for IP address %s \n " , addr ) ;
ast_variables_destroy ( var ) ;
return NULL ;
}
/* Peer found in realtime, now build it in memory */
peer = build_peer ( peername , var , NULL , 1 ) ;
ast_variables_destroy ( var ) ;
return peer ;
}
static int oh323_addrcmp_str ( struct in_addr inaddr , char * addr )
{
return strcmp ( ast_inet_ntoa ( inaddr ) , addr ) ;
}
static struct oh323_user * find_user ( const call_details_t * cd , int realtime )
{
struct oh323_user * u ;
if ( userbyalias )
u = ASTOBJ_CONTAINER_FIND ( & userl , cd - > call_source_aliases ) ;
else
u = ASTOBJ_CONTAINER_FIND_FULL ( & userl , cd - > sourceIp , addr . sin_addr , 0 , 0 , oh323_addrcmp_str ) ;
if ( ! u & & realtime )
u = realtime_user ( cd ) ;
if ( ! u & & h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Could not find user by name %s or address %s \n " , cd - > call_source_aliases , cd - > sourceIp ) ;
2006-09-19 17:07:22 +00:00
return u ;
}
static int oh323_addrcmp ( struct sockaddr_in addr , struct sockaddr_in * sin )
{
int res ;
if ( ! sin )
res = - 1 ;
else
res = inaddrcmp ( & addr , sin ) ;
return res ;
}
static struct oh323_peer * find_peer ( const char * peer , struct sockaddr_in * sin , int realtime )
{
struct oh323_peer * p ;
if ( peer )
p = ASTOBJ_CONTAINER_FIND ( & peerl , peer ) ;
else
p = ASTOBJ_CONTAINER_FIND_FULL ( & peerl , sin , addr , 0 , 0 , oh323_addrcmp ) ;
if ( ! p & & realtime )
p = realtime_peer ( peer , sin ) ;
if ( ! p & & h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Could not find peer by name %s or address %s \n " , ( peer ? peer : " <NONE> " ) , ( sin ? ast_inet_ntoa ( sin - > sin_addr ) : " <NONE> " ) ) ;
2006-09-19 17:07:22 +00:00
return p ;
}
static int create_addr ( struct oh323_pvt * pvt , char * opeer )
{
struct hostent * hp ;
struct ast_hostent ahp ;
struct oh323_peer * p ;
int portno ;
int found = 0 ;
char * port ;
char * hostn ;
char peer [ 256 ] = " " ;
2006-10-25 14:44:50 +00:00
ast_copy_string ( peer , opeer , sizeof ( peer ) ) ;
2006-09-19 17:07:22 +00:00
port = strchr ( peer , ' : ' ) ;
if ( port ) {
* port = ' \0 ' ;
port + + ;
}
pvt - > sa . sin_family = AF_INET ;
p = find_peer ( peer , NULL , 1 ) ;
if ( p ) {
found + + ;
memcpy ( & pvt - > options , & p - > options , sizeof ( pvt - > options ) ) ;
pvt - > jointcapability = pvt - > options . capability ;
if ( pvt - > options . dtmfmode ) {
if ( pvt - > options . dtmfmode & H323_DTMF_RFC2833 ) {
pvt - > nonCodecCapability | = AST_RTP_DTMF ;
} else {
pvt - > nonCodecCapability & = ~ AST_RTP_DTMF ;
}
}
if ( p - > addr . sin_addr . s_addr ) {
pvt - > sa . sin_addr = p - > addr . sin_addr ;
pvt - > sa . sin_port = p - > addr . sin_port ;
}
ASTOBJ_UNREF ( p , oh323_destroy_peer ) ;
}
if ( ! p & & ! found ) {
2004-10-01 04:50:34 +00:00
hostn = peer ;
if ( port ) {
portno = atoi ( port ) ;
} else {
2004-10-04 10:13:01 +00:00
portno = h323_signalling_port ;
2006-09-19 17:07:22 +00:00
}
2004-10-01 04:50:34 +00:00
hp = ast_gethostbyname ( hostn , & ahp ) ;
if ( hp ) {
2004-10-04 10:13:01 +00:00
memcpy ( & pvt - > sa . sin_addr , hp - > h_addr , sizeof ( pvt - > sa . sin_addr ) ) ;
pvt - > sa . sin_port = htons ( portno ) ;
2006-09-19 17:07:22 +00:00
/* Look peer by address */
p = find_peer ( NULL , & pvt - > sa , 1 ) ;
memcpy ( & pvt - > options , ( p ? & p - > options : & global_options ) , sizeof ( pvt - > options ) ) ;
pvt - > jointcapability = pvt - > options . capability ;
if ( p ) {
ASTOBJ_UNREF ( p , oh323_destroy_peer ) ;
}
if ( pvt - > options . dtmfmode ) {
if ( pvt - > options . dtmfmode & H323_DTMF_RFC2833 ) {
pvt - > nonCodecCapability | = AST_RTP_DTMF ;
} else {
pvt - > nonCodecCapability & = ~ AST_RTP_DTMF ;
}
}
return 0 ;
2004-10-01 04:50:34 +00:00
} else {
ast_log ( LOG_WARNING , " No such host: %s \n " , peer ) ;
return - 1 ;
}
2006-09-19 17:07:22 +00:00
} else if ( ! found ) {
2004-10-01 04:50:34 +00:00
return - 1 ;
2006-09-19 17:07:22 +00:00
} else {
2004-10-04 10:13:01 +00:00
return 0 ;
}
2004-09-30 19:36:46 +00:00
}
2004-12-15 23:24:13 +00:00
static struct ast_channel * oh323_request ( const char * type , int format , void * data , int * cause )
2004-09-30 19:36:46 +00:00
{
2003-03-31 07:13:36 +00:00
int oldformat ;
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
struct ast_channel * tmpc = NULL ;
2004-09-30 19:36:46 +00:00
char * dest = ( char * ) data ;
2003-03-31 07:13:36 +00:00
char * ext , * host ;
2003-06-03 07:11:52 +00:00
char * h323id = NULL ;
2005-05-11 13:27:49 +00:00
char tmp [ 256 ] , tmp1 [ 256 ] ;
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " type=%s, format=%d, data=%s. \n " , type , format , ( char * ) data ) ;
2006-09-19 17:07:22 +00:00
2004-10-04 10:13:01 +00:00
pvt = oh323_alloc ( 0 ) ;
if ( ! pvt ) {
ast_log ( LOG_WARNING , " Unable to build pvt data for '%s' \n " , ( char * ) data ) ;
return NULL ;
2006-09-19 17:07:22 +00:00
}
2003-03-31 07:13:36 +00:00
oldformat = format ;
2007-11-06 22:51:48 +00:00
format & = AST_FORMAT_AUDIO_MASK ;
2003-03-31 07:13:36 +00:00
if ( ! format ) {
ast_log ( LOG_NOTICE , " Asked to get a channel of unsupported format '%d' \n " , format ) ;
2006-09-19 17:07:22 +00:00
oh323_destroy ( pvt ) ;
if ( cause )
* cause = AST_CAUSE_INCOMPATIBLE_DESTINATION ;
2003-03-31 07:13:36 +00:00
return NULL ;
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( tmp , dest , sizeof ( tmp ) ) ;
2003-03-31 07:13:36 +00:00
host = strchr ( tmp , ' @ ' ) ;
if ( host ) {
* host = ' \0 ' ;
host + + ;
ext = tmp ;
} else {
2006-09-19 17:07:22 +00:00
ext = strrchr ( tmp , ' / ' ) ;
if ( ext )
* ext + + = ' \0 ' ;
2003-03-31 07:13:36 +00:00
host = tmp ;
}
2006-09-19 17:07:22 +00:00
strtok_r ( host , " / " , & ( h323id ) ) ;
2005-10-27 02:19:37 +00:00
if ( ! ast_strlen_zero ( h323id ) ) {
2003-06-03 07:11:52 +00:00
h323_set_id ( h323id ) ;
}
2004-01-11 17:51:35 +00:00
if ( ext ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , ext , sizeof ( pvt - > exten ) ) ;
2004-01-11 17:51:35 +00:00
}
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Extension: %s Host: %s \n " , pvt - > exten , host ) ;
2006-09-19 17:07:22 +00:00
if ( gatekeeper_disable ) {
2004-10-04 10:13:01 +00:00
if ( create_addr ( pvt , host ) ) {
oh323_destroy ( pvt ) ;
2006-09-19 17:07:22 +00:00
if ( cause )
* cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER ;
2004-10-04 10:13:01 +00:00
return NULL ;
}
2004-09-30 19:36:46 +00:00
}
2005-05-21 17:09:30 +00:00
else {
2005-04-29 04:22:47 +00:00
memcpy ( & pvt - > options , & global_options , sizeof ( pvt - > options ) ) ;
2006-09-19 17:07:22 +00:00
pvt - > jointcapability = pvt - > options . capability ;
2005-05-21 17:09:30 +00:00
if ( pvt - > options . dtmfmode ) {
if ( pvt - > options . dtmfmode & H323_DTMF_RFC2833 ) {
pvt - > nonCodecCapability | = AST_RTP_DTMF ;
} else {
pvt - > nonCodecCapability & = ~ AST_RTP_DTMF ;
}
}
}
2004-12-15 23:24:13 +00:00
2004-10-14 05:21:12 +00:00
ast_mutex_lock ( & caplock ) ;
2005-05-11 13:27:49 +00:00
/* Generate unique channel identifier */
snprintf ( tmp1 , sizeof ( tmp1 ) - 1 , " %s-%u " , host , + + unique ) ;
tmp1 [ sizeof ( tmp1 ) - 1 ] = ' \0 ' ;
2004-10-14 05:21:12 +00:00
ast_mutex_unlock ( & caplock ) ;
2005-05-11 13:27:49 +00:00
2004-10-04 10:13:01 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2005-05-11 13:27:49 +00:00
tmpc = __oh323_new ( pvt , AST_STATE_DOWN , tmp1 ) ;
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-09-30 19:36:46 +00:00
if ( ! tmpc ) {
2004-10-04 10:13:01 +00:00
oh323_destroy ( pvt ) ;
2006-09-19 17:07:22 +00:00
if ( cause )
* cause = AST_CAUSE_NORMAL_TEMPORARY_FAILURE ;
2004-09-30 19:36:46 +00:00
}
ast_update_use_count ( ) ;
2003-03-31 07:13:36 +00:00
restart_monitor ( ) ;
return tmpc ;
}
2007-02-24 20:29:41 +00:00
/*! \brief Find a call by alias */
2006-09-19 17:07:22 +00:00
static struct oh323_alias * find_alias ( const char * source_aliases , int realtime )
2003-03-31 07:13:36 +00:00
{
2003-12-24 22:38:24 +00:00
struct oh323_alias * a ;
2003-03-31 07:13:36 +00:00
2006-09-19 17:07:22 +00:00
a = ASTOBJ_CONTAINER_FIND ( & aliasl , source_aliases ) ;
if ( ! a & & realtime )
a = realtime_alias ( source_aliases ) ;
2003-12-24 22:38:24 +00:00
return a ;
2003-03-31 07:13:36 +00:00
}
2007-02-24 20:29:41 +00:00
/*! \brief
2003-03-31 07:13:36 +00:00
* Callback for sending digits from H .323 up to asterisk
*
*/
2006-09-19 17:07:22 +00:00
static int receive_digit ( unsigned call_reference , char digit , const char * token , int duration )
2003-03-31 07:13:36 +00:00
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt ;
2005-05-11 13:27:49 +00:00
int res ;
2003-03-31 07:13:36 +00:00
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2004-10-04 10:13:01 +00:00
if ( ! pvt ) {
2006-09-19 17:07:22 +00:00
ast_log ( LOG_ERROR , " Received digit '%c' (%u ms) for call %s without private structure \n " , digit , duration , token ) ;
2003-03-31 07:13:36 +00:00
return - 1 ;
}
2006-09-19 17:07:22 +00:00
if ( h323debug )
ast_log ( LOG_DTMF , " Received %s digit '%c' (%u ms) for call %s \n " , ( digit = = ' ' ? " update for " : " new " ) , ( digit = = ' ' ? pvt - > curDTMF : digit ) , duration , token ) ;
if ( pvt - > owner & & ! ast_channel_trylock ( pvt - > owner ) ) {
if ( digit = = ' ! ' )
res = ast_queue_control ( pvt - > owner , AST_CONTROL_FLASH ) ;
else {
struct ast_frame f = {
. frametype = AST_FRAME_DTMF_END ,
. subclass = digit ,
. samples = duration * 8 ,
2007-02-10 09:23:09 +00:00
. len = duration ,
2006-09-19 17:07:22 +00:00
. src = " SEND_DIGIT " ,
} ;
if ( digit = = ' ' ) { /* signalUpdate message */
f . subclass = pvt - > curDTMF ;
2008-01-27 22:35:29 +00:00
AST_SCHED_DEL ( sched , pvt - > DTMFsched ) ;
2006-09-19 17:07:22 +00:00
} else { /* Regular input or signal message */
2007-02-10 09:23:09 +00:00
if ( pvt - > DTMFsched > = 0 ) {
/* We still don't send DTMF END from previous event, send it now */
2008-01-27 22:35:29 +00:00
AST_SCHED_DEL ( sched , pvt - > DTMFsched ) ;
2007-02-10 09:23:09 +00:00
f . subclass = pvt - > curDTMF ;
f . samples = f . len = 0 ;
ast_queue_frame ( pvt - > owner , & f ) ;
/* Restore values */
f . subclass = digit ;
f . samples = duration * 8 ;
f . len = duration ;
}
2006-09-19 17:07:22 +00:00
if ( duration ) { /* This is a signal, signalUpdate follows */
f . frametype = AST_FRAME_DTMF_BEGIN ;
pvt - > DTMFsched = ast_sched_add ( sched , duration , oh323_simulate_dtmf_end , pvt ) ;
if ( h323debug )
ast_log ( LOG_DTMF , " Scheduled DTMF END simulation for %d ms, id=%d \n " , duration , pvt - > DTMFsched ) ;
}
pvt - > curDTMF = digit ;
}
res = ast_queue_frame ( pvt - > owner , & f ) ;
}
ast_channel_unlock ( pvt - > owner ) ;
2006-08-15 14:55:30 +00:00
} else {
2006-09-19 17:07:22 +00:00
if ( digit = = ' ! ' )
pvt - > newcontrol = AST_CONTROL_FLASH ;
else {
pvt - > newduration = duration ;
pvt - > newdigit = digit ;
}
2006-08-15 14:55:30 +00:00
res = 0 ;
}
2005-05-11 13:27:49 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
return res ;
2003-03-31 07:13:36 +00:00
}
2007-02-24 20:29:41 +00:00
/*! \brief
2004-10-10 12:20:18 +00:00
* Callback function used to inform the H .323 stack of the local rtp ip / port details
2003-03-31 07:13:36 +00:00
*
2007-02-24 20:29:41 +00:00
* \ return Returns the local RTP information
2003-03-31 07:13:36 +00:00
*/
2006-09-19 17:07:22 +00:00
static struct rtp_info * external_rtp_create ( unsigned call_reference , const char * token )
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
struct sockaddr_in us ;
2003-08-25 09:54:36 +00:00
struct rtp_info * info ;
2003-03-31 07:13:36 +00:00
2007-06-03 06:10:27 +00:00
info = ast_calloc ( 1 , sizeof ( * info ) ) ;
2004-10-10 12:20:18 +00:00
if ( ! info ) {
ast_log ( LOG_ERROR , " Unable to allocated info structure, this is very bad \n " ) ;
return NULL ;
}
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2004-10-04 10:13:01 +00:00
if ( ! pvt ) {
2007-06-03 06:10:27 +00:00
ast_free ( info ) ;
2004-10-10 12:20:18 +00:00
ast_log ( LOG_ERROR , " Unable to find call %s(%d) \n " , token , call_reference ) ;
2003-08-25 09:54:36 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2006-09-19 17:07:22 +00:00
if ( ! pvt - > rtp )
__oh323_rtp_create ( pvt ) ;
if ( ! pvt - > rtp ) {
ast_mutex_unlock ( & pvt - > lock ) ;
2007-06-03 06:10:27 +00:00
ast_free ( info ) ;
2006-09-19 17:07:22 +00:00
ast_log ( LOG_ERROR , " No RTP stream is available for call %s (%d) " , token , call_reference ) ;
return NULL ;
}
2004-10-14 05:21:12 +00:00
/* figure out our local RTP port and tell the H.323 stack about it */
2004-10-04 10:13:01 +00:00
ast_rtp_get_us ( pvt - > rtp , & us ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-07-27 04:39:53 +00:00
2006-10-25 14:44:50 +00:00
ast_copy_string ( info - > addr , ast_inet_ntoa ( us . sin_addr ) , sizeof ( info - > addr ) ) ;
2003-08-25 09:54:36 +00:00
info - > port = ntohs ( us . sin_port ) ;
2005-05-11 13:27:49 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Sending RTP 'US' %s:%d \n " , info - > addr , info - > port ) ;
2003-08-25 09:54:36 +00:00
return info ;
2003-03-31 07:13:36 +00:00
}
2007-06-07 23:07:25 +00:00
/*
2004-12-21 00:07:56 +00:00
* Definition taken from rtp . c for rtpPayloadType because we need it here .
*/
2007-06-07 23:07:25 +00:00
2004-12-21 00:07:56 +00:00
struct rtpPayloadType {
2006-09-19 17:07:22 +00:00
int isAstFormat ; /* whether the following code is an AST_FORMAT */
2004-12-21 00:07:56 +00:00
int code ;
} ;
2007-02-24 20:29:41 +00:00
/*! \brief
2006-09-19 17:07:22 +00:00
* Call - back function passing remote ip / port information from H .323 to asterisk
2004-10-10 12:20:18 +00:00
*
2006-09-19 17:07:22 +00:00
* Returns nothing
2004-10-10 12:20:18 +00:00
*/
2006-09-19 17:07:22 +00:00
static void setup_rtp_connection ( unsigned call_reference , const char * remoteIp , int remotePort , const char * token , int pt )
2004-10-10 12:20:18 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2004-10-10 12:20:18 +00:00
struct sockaddr_in them ;
2004-12-21 00:07:56 +00:00
struct rtpPayloadType rtptype ;
2006-09-19 17:07:22 +00:00
int nativeformats_changed ;
enum { NEED_NONE , NEED_HOLD , NEED_UNHOLD } rtp_change = NEED_NONE ;
2004-10-10 12:20:18 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Setting up RTP connection for %s \n " , token ) ;
2005-05-11 13:27:49 +00:00
2004-10-10 12:20:18 +00:00
/* Find the call or allocate a private structure if call not found */
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2004-10-10 12:20:18 +00:00
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: rtp \n " ) ;
return ;
}
2005-04-04 15:54:34 +00:00
if ( pvt - > alreadygone ) {
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
2006-09-19 17:07:22 +00:00
if ( ! pvt - > rtp )
__oh323_rtp_create ( pvt ) ;
2004-12-21 00:07:56 +00:00
2006-09-21 18:48:53 +00:00
if ( ( pt = = 2 ) & & ( pvt - > jointcapability & AST_FORMAT_G726_AAL2 ) ) {
ast_rtp_set_rtpmap_type ( pvt - > rtp , pt , " audio " , " G726-32 " , AST_RTP_OPT_G726_NONSTANDARD ) ;
}
2004-10-10 12:20:18 +00:00
them . sin_family = AF_INET ;
2004-10-28 06:06:58 +00:00
/* only works for IPv4 */
2006-09-19 17:07:22 +00:00
them . sin_addr . s_addr = inet_addr ( remoteIp ) ;
2004-10-10 12:20:18 +00:00
them . sin_port = htons ( remotePort ) ;
2004-12-15 23:24:13 +00:00
2006-09-19 17:07:22 +00:00
if ( them . sin_addr . s_addr ) {
ast_rtp_set_peer ( pvt - > rtp , & them ) ;
if ( pvt - > recvonly ) {
pvt - > recvonly = 0 ;
rtp_change = NEED_UNHOLD ;
}
} else {
ast_rtp_stop ( pvt - > rtp ) ;
if ( ! pvt - > recvonly ) {
pvt - > recvonly = 1 ;
rtp_change = NEED_HOLD ;
}
}
/* Change native format to reflect information taken from OLC/OLCAck */
nativeformats_changed = 0 ;
if ( pt ! = 128 & & pvt - > rtp ) { /* Payload type is invalid, so try to use previously decided */
rtptype = ast_rtp_lookup_pt ( pvt - > rtp , pt ) ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Native format is set to %d from %d by RTP payload type %d \n " , rtptype . code , pvt - > nativeformats , pt ) ;
2006-09-19 17:07:22 +00:00
if ( pvt - > nativeformats ! = rtptype . code ) {
pvt - > nativeformats = rtptype . code ;
nativeformats_changed = 1 ;
}
} else if ( h323debug )
ast_log ( LOG_NOTICE , " Payload type is unknown, formats isn't changed \n " ) ;
/* Don't try to lock the channel if nothing changed */
if ( nativeformats_changed | | pvt - > options . progress_audio | | ( rtp_change ! = NEED_NONE ) ) {
if ( pvt - > owner & & ! ast_channel_trylock ( pvt - > owner ) ) {
/* Re-build translation path only if native format(s) has been changed */
if ( pvt - > owner - > nativeformats ! = pvt - > nativeformats ) {
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Native format changed to %d from %d, read format is %d, write format is %d \n " , pvt - > nativeformats , pvt - > owner - > nativeformats , pvt - > owner - > readformat , pvt - > owner - > writeformat ) ;
2006-09-19 17:07:22 +00:00
pvt - > owner - > nativeformats = pvt - > nativeformats ;
ast_set_read_format ( pvt - > owner , pvt - > owner - > readformat ) ;
ast_set_write_format ( pvt - > owner , pvt - > owner - > writeformat ) ;
}
if ( pvt - > options . progress_audio )
ast_queue_control ( pvt - > owner , AST_CONTROL_PROGRESS ) ;
switch ( rtp_change ) {
case NEED_HOLD :
ast_queue_control ( pvt - > owner , AST_CONTROL_HOLD ) ;
break ;
case NEED_UNHOLD :
ast_queue_control ( pvt - > owner , AST_CONTROL_UNHOLD ) ;
break ;
default :
break ;
}
ast_channel_unlock ( pvt - > owner ) ;
}
else {
if ( pvt - > options . progress_audio )
pvt - > newcontrol = AST_CONTROL_PROGRESS ;
else if ( rtp_change = = NEED_HOLD )
pvt - > newcontrol = AST_CONTROL_HOLD ;
else if ( rtp_change = = NEED_UNHOLD )
pvt - > newcontrol = AST_CONTROL_UNHOLD ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " RTP connection preparation for %s is pending... \n " , token ) ;
2006-09-19 17:07:22 +00:00
}
}
2005-07-27 04:45:11 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " RTP connection prepared for %s \n " , token ) ;
2004-12-21 00:07:56 +00:00
2004-10-10 12:20:18 +00:00
return ;
}
2007-02-24 20:29:41 +00:00
/*! \brief
2006-09-19 17:07:22 +00:00
* Call - back function to signal asterisk that the channel has been answered
2004-10-10 12:20:18 +00:00
* Returns nothing
*/
2006-09-19 17:07:22 +00:00
static void connection_made ( unsigned call_reference , const char * token )
2004-10-10 12:20:18 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Call %s answered \n " , token ) ;
2005-05-11 13:27:49 +00:00
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2004-10-10 12:20:18 +00:00
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: connection \n " ) ;
return ;
}
2005-04-04 15:54:34 +00:00
/* Inform asterisk about remote party connected only on outgoing calls */
if ( ! pvt - > outgoing ) {
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
2006-09-19 17:07:22 +00:00
/* Do not send ANSWER message more than once */
if ( ! pvt - > connection_established ) {
pvt - > connection_established = 1 ;
update_state ( pvt , - 1 , AST_CONTROL_ANSWER ) ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-10-10 12:20:18 +00:00
return ;
}
2006-09-19 17:07:22 +00:00
static int progress ( unsigned call_reference , const char * token , int inband )
2004-12-15 23:24:13 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2004-12-15 23:24:13 +00:00
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Received ALERT/PROGRESS message for %s tones \n " , ( inband ? " inband " : " self-generated " ) ) ;
2004-12-15 23:24:13 +00:00
2005-05-11 13:27:49 +00:00
pvt = find_call_locked ( call_reference , token ) ;
if ( ! pvt ) {
2004-12-15 23:24:13 +00:00
ast_log ( LOG_ERROR , " Private structure not found in progress. \n " ) ;
return - 1 ;
}
2005-05-11 13:27:49 +00:00
if ( ! pvt - > owner ) {
ast_mutex_unlock ( & pvt - > lock ) ;
2004-12-15 23:24:13 +00:00
ast_log ( LOG_ERROR , " No Asterisk channel associated with private structure. \n " ) ;
return - 1 ;
}
2006-09-19 17:07:22 +00:00
update_state ( pvt , - 1 , ( inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING ) ) ;
2005-05-11 13:27:49 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-12-15 23:24:13 +00:00
return 0 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief
2003-03-31 07:13:36 +00:00
* Call - back function for incoming calls
*
* Returns 1 on success
*/
2006-09-19 17:07:22 +00:00
static call_options_t * setup_incoming_call ( call_details_t * cd )
2003-03-31 07:13:36 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
struct oh323_user * user = NULL ;
struct oh323_alias * alias = NULL ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Setting up incoming call for %s \n " , cd - > call_token ) ;
2005-04-04 15:54:34 +00:00
2003-03-31 07:13:36 +00:00
/* allocate the call*/
2005-05-19 16:17:08 +00:00
pvt = oh323_alloc ( cd - > call_reference ) ;
2003-03-31 07:13:36 +00:00
2004-10-04 10:13:01 +00:00
if ( ! pvt ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Unable to allocate private structure, this is bad. \n " ) ;
2006-09-19 17:07:22 +00:00
cleanup_call_details ( cd ) ;
2004-12-15 23:24:13 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
/* Populate the call details in the private structure */
2005-05-19 16:17:08 +00:00
memcpy ( & pvt - > cd , cd , sizeof ( pvt - > cd ) ) ;
memcpy ( & pvt - > options , & global_options , sizeof ( pvt - > options ) ) ;
2006-09-19 17:07:22 +00:00
pvt - > jointcapability = pvt - > options . capability ;
2003-03-31 07:13:36 +00:00
if ( h323debug ) {
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , " Setting up Call \n " ) ;
ast_verb ( 3 , " \t Call token: [%s] \n " , pvt - > cd . call_token ) ;
ast_verb ( 3 , " \t Calling party name: [%s] \n " , pvt - > cd . call_source_name ) ;
ast_verb ( 3 , " \t Calling party number: [%s] \n " , pvt - > cd . call_source_e164 ) ;
ast_verb ( 3 , " \t Called party name: [%s] \n " , pvt - > cd . call_dest_alias ) ;
ast_verb ( 3 , " \t Called party number: [%s] \n " , pvt - > cd . call_dest_e164 ) ;
2006-09-19 17:07:22 +00:00
if ( pvt - > cd . redirect_reason > = 0 )
2007-07-26 15:49:18 +00:00
ast_verb ( 3 , " \t Redirecting party number: [%s] (reason %d) \n " , pvt - > cd . redirect_number , pvt - > cd . redirect_reason ) ;
ast_verb ( 3 , " \t Calling party IP: [%s] \n " , pvt - > cd . sourceIp ) ;
2003-03-31 07:13:36 +00:00
}
/* Decide if we are allowing Gatekeeper routed calls*/
2006-09-19 17:07:22 +00:00
if ( ( ! strcasecmp ( cd - > sourceIp , gatekeeper ) ) & & ( gkroute = = - 1 ) & & ! gatekeeper_disable ) {
2005-05-19 16:17:08 +00:00
if ( ! ast_strlen_zero ( cd - > call_dest_e164 ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , cd - > call_dest_e164 , sizeof ( pvt - > exten ) ) ;
ast_copy_string ( pvt - > context , default_context , sizeof ( pvt - > context ) ) ;
2003-03-31 07:13:36 +00:00
} else {
2006-09-19 17:07:22 +00:00
alias = find_alias ( cd - > call_dest_alias , 1 ) ;
2003-03-31 07:13:36 +00:00
if ( ! alias ) {
2005-05-19 16:17:08 +00:00
ast_log ( LOG_ERROR , " Call for %s rejected, alias not found \n " , cd - > call_dest_alias ) ;
2006-09-19 17:07:22 +00:00
oh323_destroy ( pvt ) ;
2004-12-15 23:24:13 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , alias - > name , sizeof ( pvt - > exten ) ) ;
ast_copy_string ( pvt - > context , alias - > context , sizeof ( pvt - > context ) ) ;
2003-03-31 07:13:36 +00:00
}
2005-05-11 13:27:49 +00:00
} else {
2006-09-19 17:07:22 +00:00
/* Either this call is not from the Gatekeeper
2003-03-31 07:13:36 +00:00
or we are not allowing gk routed calls */
2006-09-19 17:07:22 +00:00
user = find_user ( cd , 1 ) ;
2003-03-31 07:13:36 +00:00
if ( ! user ) {
2006-09-19 17:07:22 +00:00
if ( ! acceptAnonymous ) {
ast_log ( LOG_NOTICE , " Anonymous call from '%s@%s' rejected \n " , pvt - > cd . call_source_aliases , pvt - > cd . sourceIp ) ;
oh323_destroy ( pvt ) ;
return NULL ;
2003-03-31 07:13:36 +00:00
}
2004-05-03 22:19:03 +00:00
if ( ast_strlen_zero ( default_context ) ) {
2006-09-19 17:07:22 +00:00
ast_log ( LOG_ERROR , " Call from '%s@%s' rejected due to no default context \n " , pvt - > cd . call_source_aliases , pvt - > cd . sourceIp ) ;
oh323_destroy ( pvt ) ;
2004-12-15 23:24:13 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > context , default_context , sizeof ( pvt - > context ) ) ;
2006-09-19 17:07:22 +00:00
if ( ! ast_strlen_zero ( pvt - > cd . call_dest_e164 ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , cd - > call_dest_e164 , sizeof ( pvt - > exten ) ) ;
2006-09-19 17:07:22 +00:00
} else {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , cd - > call_dest_alias , sizeof ( pvt - > exten ) ) ;
2006-09-19 17:07:22 +00:00
}
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Sending %s@%s to context [%s] extension %s \n " , cd - > call_source_aliases , cd - > sourceIp , pvt - > context , pvt - > exten ) ;
2005-05-19 16:17:08 +00:00
} else {
2003-03-31 20:26:08 +00:00
if ( user - > host ) {
2006-09-19 17:07:22 +00:00
if ( strcasecmp ( cd - > sourceIp , ast_inet_ntoa ( user - > addr . sin_addr ) ) ) {
2004-05-20 21:56:12 +00:00
if ( ast_strlen_zero ( user - > context ) ) {
2005-05-11 13:27:49 +00:00
if ( ast_strlen_zero ( default_context ) ) {
2005-05-19 16:17:08 +00:00
ast_log ( LOG_ERROR , " Call from '%s' rejected due to non-matching IP address (%s) and no default context \n " , user - > name , cd - > sourceIp ) ;
2006-09-19 17:07:22 +00:00
oh323_destroy ( pvt ) ;
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
return NULL ;
2004-05-20 21:56:12 +00:00
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > context , default_context , sizeof ( pvt - > context ) ) ;
2004-05-20 21:56:12 +00:00
} else {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > context , user - > context , sizeof ( pvt - > context ) ) ;
2003-04-11 20:28:25 +00:00
}
2004-10-04 10:13:01 +00:00
pvt - > exten [ 0 ] = ' i ' ;
pvt - > exten [ 1 ] = ' \0 ' ;
2005-05-19 16:17:08 +00:00
ast_log ( LOG_ERROR , " Call from '%s' rejected due to non-matching IP address (%s)s \n " , user - > name , cd - > sourceIp ) ;
2006-09-19 17:07:22 +00:00
oh323_destroy ( pvt ) ;
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
2005-05-19 16:17:08 +00:00
return NULL ; /* XXX: Hmmm... Why to setup context if we drop connection immediately??? */
2003-03-31 20:26:08 +00:00
}
2003-03-31 19:26:15 +00:00
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > context , user - > context , sizeof ( pvt - > context ) ) ;
2005-05-11 13:27:49 +00:00
memcpy ( & pvt - > options , & user - > options , sizeof ( pvt - > options ) ) ;
2006-09-19 17:07:22 +00:00
pvt - > jointcapability = pvt - > options . capability ;
2004-10-04 10:13:01 +00:00
if ( ! ast_strlen_zero ( pvt - > cd . call_dest_e164 ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , cd - > call_dest_e164 , sizeof ( pvt - > exten ) ) ;
2003-03-31 07:13:36 +00:00
} else {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , cd - > call_dest_alias , sizeof ( pvt - > exten ) ) ;
2003-03-31 07:13:36 +00:00
}
2004-05-03 22:19:03 +00:00
if ( ! ast_strlen_zero ( user - > accountcode ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > accountcode , user - > accountcode , sizeof ( pvt - > accountcode ) ) ;
2006-09-19 17:07:22 +00:00
}
2004-10-22 19:04:02 +00:00
if ( user - > amaflags ) {
pvt - > amaflags = user - > amaflags ;
2006-09-19 17:07:22 +00:00
}
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
}
2003-03-31 07:13:36 +00:00
}
2005-05-11 13:27:49 +00:00
return & pvt - > options ;
2004-06-15 20:56:06 +00:00
}
2003-03-31 07:13:36 +00:00
2007-02-24 20:29:41 +00:00
/*! \brief
2004-06-15 20:56:06 +00:00
* Call - back function to start PBX when OpenH323 ready to serve incoming call
*
* Returns 1 on success
*/
2004-09-19 16:53:01 +00:00
static int answer_call ( unsigned call_reference , const char * token )
2004-06-15 20:56:06 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2004-06-15 20:56:06 +00:00
struct ast_channel * c = NULL ;
2006-09-19 17:07:22 +00:00
enum { ext_original , ext_s , ext_i , ext_notexists } try_exten ;
char tmp_exten [ sizeof ( pvt - > exten ) ] ;
2004-09-19 16:53:01 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Preparing Asterisk to answer for %s \n " , token ) ;
2005-04-04 15:54:34 +00:00
2004-06-15 20:56:06 +00:00
/* Find the call or allocate a private structure if call not found */
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2004-10-04 10:13:01 +00:00
if ( ! pvt ) {
2004-06-15 20:56:06 +00:00
ast_log ( LOG_ERROR , " Something is wrong: answer_call \n " ) ;
return 0 ;
}
2006-09-19 17:07:22 +00:00
/* Check if requested extension@context pair exists in the dialplan */
2006-10-25 14:44:50 +00:00
ast_copy_string ( tmp_exten , pvt - > exten , sizeof ( tmp_exten ) ) ;
2006-09-19 17:07:22 +00:00
/* Try to find best extension in specified context */
if ( ( tmp_exten [ 0 ] ! = ' \0 ' ) & & ( tmp_exten [ 1 ] = = ' \0 ' ) ) {
if ( tmp_exten [ 0 ] = = ' s ' )
try_exten = ext_s ;
else if ( tmp_exten [ 0 ] = = ' i ' )
try_exten = ext_i ;
else
try_exten = ext_original ;
} else
try_exten = ext_original ;
do {
if ( ast_exists_extension ( NULL , pvt - > context , tmp_exten , 1 , NULL ) )
break ;
switch ( try_exten ) {
case ext_original :
tmp_exten [ 0 ] = ' s ' ;
tmp_exten [ 1 ] = ' \0 ' ;
try_exten = ext_s ;
break ;
case ext_s :
tmp_exten [ 0 ] = ' i ' ;
try_exten = ext_i ;
break ;
case ext_i :
try_exten = ext_notexists ;
break ;
default :
break ;
}
} while ( try_exten ! = ext_notexists ) ;
/* Drop the call if we don't have <exten>, s and i extensions */
if ( try_exten = = ext_notexists ) {
ast_log ( LOG_NOTICE , " Dropping call because extensions '%s', 's' and 'i' doesn't exists in context [%s] \n " , pvt - > exten , pvt - > context ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
h323_clear_call ( token , AST_CAUSE_UNALLOCATED ) ;
return 0 ;
} else if ( ( try_exten ! = ext_original ) & & ( strcmp ( pvt - > exten , tmp_exten ) ! = 0 ) ) {
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Going to extension %s@%s because %s@%s isn't exists \n " , tmp_exten , pvt - > context , pvt - > exten , pvt - > context ) ;
2006-10-25 14:44:50 +00:00
ast_copy_string ( pvt - > exten , tmp_exten , sizeof ( pvt - > exten ) ) ;
2006-09-19 17:07:22 +00:00
}
2004-06-15 20:56:06 +00:00
/* allocate a channel and tell asterisk about it */
2005-05-11 13:27:49 +00:00
c = __oh323_new ( pvt , AST_STATE_RINGING , pvt - > cd . call_token ) ;
2005-02-09 21:15:44 +00:00
/* And release when done */
ast_mutex_unlock ( & pvt - > lock ) ;
2004-06-15 20:56:06 +00:00
if ( ! c ) {
ast_log ( LOG_ERROR , " Couldn't create channel. This is bad \n " ) ;
return 0 ;
}
2003-12-24 22:38:24 +00:00
return 1 ;
2003-03-31 07:13:36 +00:00
}
2007-02-24 20:29:41 +00:00
/*! \brief
2003-03-31 07:13:36 +00:00
* Call - back function to establish an outgoing H .323 call
2006-09-19 17:07:22 +00:00
*
* Returns 1 on success
2003-03-31 07:13:36 +00:00
*/
2006-09-19 17:07:22 +00:00
static int setup_outgoing_call ( call_details_t * cd )
2005-05-19 16:17:08 +00:00
{
/* Use argument here or free it immediately */
cleanup_call_details ( cd ) ;
2003-03-31 07:13:36 +00:00
return 1 ;
}
2007-02-24 20:29:41 +00:00
/*! \brief
2004-05-20 07:07:18 +00:00
* Call - back function to signal asterisk that the channel is ringing
* Returns nothing
*/
2006-09-19 17:07:22 +00:00
static void chan_ringing ( unsigned call_reference , const char * token )
2004-05-20 07:07:18 +00:00
{
2005-05-19 16:17:08 +00:00
struct oh323_pvt * pvt ;
2004-05-20 07:07:18 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Ringing on %s \n " , token ) ;
2005-04-04 15:54:34 +00:00
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2005-07-27 04:45:11 +00:00
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: ringing \n " ) ;
return ;
2004-05-20 07:07:18 +00:00
}
2005-05-19 16:17:08 +00:00
if ( ! pvt - > owner ) {
ast_mutex_unlock ( & pvt - > lock ) ;
ast_log ( LOG_ERROR , " Channel has no owner \n " ) ;
return ;
}
2006-09-19 17:07:22 +00:00
update_state ( pvt , AST_STATE_RINGING , AST_CONTROL_RINGING ) ;
2005-05-19 16:17:08 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
2004-05-20 07:07:18 +00:00
}
2007-02-24 20:29:41 +00:00
/*! \brief
2003-03-31 07:13:36 +00:00
* Call - back function to cleanup communication
* Returns nothing ,
*/
2005-05-19 16:17:08 +00:00
static void cleanup_connection ( unsigned call_reference , const char * call_token )
2006-09-19 17:07:22 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2005-04-04 15:54:34 +00:00
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Cleaning connection to %s \n " , call_token ) ;
2006-09-19 17:07:22 +00:00
2005-04-04 15:54:34 +00:00
while ( 1 ) {
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , call_token ) ;
2005-04-04 15:54:34 +00:00
if ( ! pvt ) {
2005-05-11 13:27:49 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " No connection for %s \n " , call_token ) ;
2005-04-04 15:54:34 +00:00
return ;
}
2006-09-19 17:07:22 +00:00
if ( ! pvt - > owner | | ! ast_channel_trylock ( pvt - > owner ) )
2005-04-04 15:54:34 +00:00
break ;
# if 1
2005-05-19 16:17:08 +00:00
ast_log ( LOG_NOTICE , " Avoiding H.323 destory deadlock on %s \n " , call_token ) ;
2007-11-24 13:57:46 +00:00
# ifdef DEBUG_THREADS
/* XXX to be completed
* If we want to print more info on who is holding the lock ,
* implement the relevant code in lock . h and use the routines
* supplied there .
*/
2005-04-04 15:54:34 +00:00
# endif
# endif
ast_mutex_unlock ( & pvt - > lock ) ;
usleep ( 1 ) ;
2003-03-31 07:13:36 +00:00
}
2004-10-04 10:13:01 +00:00
if ( pvt - > rtp ) {
2003-03-31 07:13:36 +00:00
/* Immediately stop RTP */
2005-05-19 16:17:08 +00:00
ast_rtp_destroy ( pvt - > rtp ) ;
pvt - > rtp = NULL ;
2003-03-31 07:13:36 +00:00
}
2005-04-04 15:54:34 +00:00
/* Free dsp used for in-band DTMF detection */
if ( pvt - > vad ) {
ast_dsp_free ( pvt - > vad ) ;
pvt - > vad = NULL ;
}
cleanup_call_details ( & pvt - > cd ) ;
2004-10-04 10:13:01 +00:00
pvt - > alreadygone = 1 ;
2006-09-19 17:07:22 +00:00
/* Send hangup */
2004-10-04 10:13:01 +00:00
if ( pvt - > owner ) {
2005-04-04 15:54:34 +00:00
pvt - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
2008-05-22 16:29:54 +00:00
ast_queue_hangup ( pvt - > owner ) ;
2006-09-19 17:07:22 +00:00
ast_channel_unlock ( pvt - > owner ) ;
2005-04-04 15:54:34 +00:00
}
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-05-11 13:27:49 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Connection to %s cleaned \n " , call_token ) ;
2006-09-19 17:07:22 +00:00
return ;
2003-03-31 07:13:36 +00:00
}
2005-04-04 15:54:34 +00:00
static void hangup_connection ( unsigned int call_reference , const char * token , int cause )
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2005-04-04 15:54:34 +00:00
2007-06-14 19:39:12 +00:00
if ( h323debug )
ast_debug ( 1 , " Hanging up connection to %s with cause %d \n " , token , cause ) ;
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2005-04-04 15:54:34 +00:00
if ( ! pvt ) {
2007-06-14 19:39:12 +00:00
if ( h323debug )
ast_debug ( 1 , " Connection to %s already cleared \n " , token ) ;
2005-04-04 15:54:34 +00:00
return ;
}
2006-09-19 17:07:22 +00:00
if ( pvt - > owner & & ! ast_channel_trylock ( pvt - > owner ) ) {
2005-04-04 15:54:34 +00:00
pvt - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
pvt - > owner - > hangupcause = pvt - > hangupcause = cause ;
2008-05-22 16:29:54 +00:00
ast_queue_hangup_with_cause ( pvt - > owner , cause ) ;
2006-09-19 17:07:22 +00:00
ast_channel_unlock ( pvt - > owner ) ;
2005-04-04 15:54:34 +00:00
}
else {
pvt - > needhangup = 1 ;
pvt - > hangupcause = cause ;
2006-09-19 17:07:22 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Hangup for %s is pending \n " , token ) ;
2005-04-04 15:54:34 +00:00
}
ast_mutex_unlock ( & pvt - > lock ) ;
}
2006-09-25 09:03:14 +00:00
static void set_dtmf_payload ( unsigned call_reference , const char * token , int payload , int is_cisco )
2004-12-15 23:24:13 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2004-12-15 23:24:13 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Setting %s DTMF payload to %d on %s \n " , ( is_cisco ? " Cisco " : " RFC2833 " ) , payload , token ) ;
2005-04-04 15:54:34 +00:00
2005-05-11 13:27:49 +00:00
pvt = find_call_locked ( call_reference , token ) ;
2004-12-15 23:24:13 +00:00
if ( ! pvt ) {
return ;
}
if ( pvt - > rtp ) {
2006-09-25 09:03:14 +00:00
ast_rtp_set_rtpmap_type ( pvt - > rtp , payload , " audio " , ( is_cisco ? " cisco-telephone-event " : " telephone-event " ) , 0 ) ;
2004-12-15 23:24:13 +00:00
}
2006-09-25 09:03:14 +00:00
pvt - > dtmf_pt [ is_cisco ? 1 : 0 ] = payload ;
2004-12-15 23:24:13 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " DTMF payload on %s set to %d \n " , token , payload ) ;
2004-12-15 23:24:13 +00:00
}
2006-09-20 16:24:00 +00:00
static void set_peer_capabilities ( unsigned call_reference , const char * token , int capabilities , struct ast_codec_pref * prefs )
2006-09-19 17:07:22 +00:00
{
struct oh323_pvt * pvt ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Got remote capabilities from connection %s \n " , token ) ;
2006-09-19 17:07:22 +00:00
pvt = find_call_locked ( call_reference , token ) ;
if ( ! pvt )
return ;
pvt - > peercapability = capabilities ;
pvt - > jointcapability = pvt - > options . capability & capabilities ;
2006-09-20 16:24:00 +00:00
if ( prefs ) {
memcpy ( & pvt - > peer_prefs , prefs , sizeof ( pvt - > peer_prefs ) ) ;
if ( h323debug ) {
int i ;
for ( i = 0 ; i < 32 ; + + i ) {
2007-02-10 09:23:09 +00:00
if ( ! prefs - > order [ i ] )
break ;
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " prefs[%d]=%s:%d \n " , i , ( prefs - > order [ i ] ? ast_getformatname ( 1 < < ( prefs - > order [ i ] - 1 ) ) : " <none> " ) , prefs - > framing [ i ] ) ;
2006-09-20 16:24:00 +00:00
}
}
if ( pvt - > rtp )
ast_rtp_codec_setpref ( pvt - > rtp , & pvt - > peer_prefs ) ;
}
2006-09-19 17:07:22 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
}
2005-05-19 19:13:19 +00:00
static void set_local_capabilities ( unsigned call_reference , const char * token )
{
struct oh323_pvt * pvt ;
2006-09-19 17:07:22 +00:00
int capability , dtmfmode , pref_codec ;
struct ast_codec_pref prefs ;
2005-05-19 19:13:19 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Setting capabilities for connection %s \n " , token ) ;
2005-05-19 19:13:19 +00:00
pvt = find_call_locked ( call_reference , token ) ;
if ( ! pvt )
return ;
2006-09-19 17:07:22 +00:00
capability = ( pvt - > jointcapability ) ? pvt - > jointcapability : pvt - > options . capability ;
2005-05-21 17:09:30 +00:00
dtmfmode = pvt - > options . dtmfmode ;
2006-09-19 17:07:22 +00:00
prefs = pvt - > options . prefs ;
pref_codec = pvt - > pref_codec ;
2005-05-19 19:13:19 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2006-09-19 17:07:22 +00:00
h323_set_capabilities ( token , capability , dtmfmode , & prefs , pref_codec ) ;
2005-05-19 19:13:19 +00:00
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Capabilities for connection %s is set \n " , token ) ;
2005-05-19 19:13:19 +00:00
}
2006-09-28 10:41:38 +00:00
static void remote_hold ( unsigned call_reference , const char * token , int is_hold )
{
struct oh323_pvt * pvt ;
if ( h323debug )
2007-06-14 19:39:12 +00:00
ast_debug ( 1 , " Setting %shold status for connection %s \n " , ( is_hold ? " " : " un " ) , token ) ;
2006-09-28 10:41:38 +00:00
pvt = find_call_locked ( call_reference , token ) ;
if ( ! pvt )
return ;
if ( pvt - > owner & & ! ast_channel_trylock ( pvt - > owner ) ) {
if ( is_hold )
ast_queue_control ( pvt - > owner , AST_CONTROL_HOLD ) ;
else
ast_queue_control ( pvt - > owner , AST_CONTROL_UNHOLD ) ;
ast_channel_unlock ( pvt - > owner ) ;
}
else {
if ( is_hold )
pvt - > newcontrol = AST_CONTROL_HOLD ;
else
pvt - > newcontrol = AST_CONTROL_UNHOLD ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
}
2003-03-31 07:13:36 +00:00
static void * do_monitor ( void * data )
{
int res ;
2004-10-15 07:07:50 +00:00
int reloading ;
2003-03-31 07:13:36 +00:00
struct oh323_pvt * oh323 = NULL ;
2006-09-19 17:07:22 +00:00
2004-10-22 19:04:02 +00:00
for ( ; ; ) {
2005-05-19 16:17:08 +00:00
/* Check for a reload request */
ast_mutex_lock ( & h323_reload_lock ) ;
reloading = h323_reloading ;
h323_reloading = 0 ;
ast_mutex_unlock ( & h323_reload_lock ) ;
if ( reloading ) {
2007-07-26 15:49:18 +00:00
ast_verb ( 1 , " Reloading H.323 \n " ) ;
2005-05-19 16:17:08 +00:00
h323_do_reload ( ) ;
}
2003-03-31 07:13:36 +00:00
/* Check for interfaces needing to be killed */
2006-09-23 18:28:23 +00:00
if ( ! ast_mutex_trylock ( & iflock ) ) {
2006-09-19 17:07:22 +00:00
# if 1
2006-09-23 18:28:23 +00:00
do {
for ( oh323 = iflist ; oh323 ; oh323 = oh323 - > next ) {
if ( ! ast_mutex_trylock ( & oh323 - > lock ) ) {
if ( oh323 - > needdestroy ) {
__oh323_destroy ( oh323 ) ;
break ;
}
ast_mutex_unlock ( & oh323 - > lock ) ;
}
}
} while ( /*oh323*/ 0 ) ;
# else
restartsearch :
oh323 = iflist ;
while ( oh323 ) {
2006-09-19 17:07:22 +00:00
if ( ! ast_mutex_trylock ( & oh323 - > lock ) ) {
if ( oh323 - > needdestroy ) {
__oh323_destroy ( oh323 ) ;
2006-09-23 18:28:23 +00:00
goto restartsearch ;
2006-09-19 17:07:22 +00:00
}
ast_mutex_unlock ( & oh323 - > lock ) ;
2006-09-23 18:28:23 +00:00
oh323 = oh323 - > next ;
2006-09-19 17:07:22 +00:00
}
}
# endif
2006-09-23 18:28:23 +00:00
ast_mutex_unlock ( & iflock ) ;
} else
oh323 = ( struct oh323_pvt * ) 1 ; /* Force fast loop */
2004-10-15 07:07:50 +00:00
pthread_testcancel ( ) ;
2003-03-31 07:13:36 +00:00
/* Wait for sched or io */
res = ast_sched_wait ( sched ) ;
2004-10-15 07:07:50 +00:00
if ( ( res < 0 ) | | ( res > 1000 ) ) {
2003-03-31 07:13:36 +00:00
res = 1000 ;
2004-10-15 07:07:50 +00:00
}
2006-09-19 17:07:22 +00:00
/* Do not wait if some channel(s) is destroyed, probably, more available too */
if ( oh323 )
res = 1 ;
2003-03-31 07:13:36 +00:00
res = ast_io_wait ( io , res ) ;
2005-04-04 15:54:34 +00:00
pthread_testcancel ( ) ;
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & monlock ) ;
2004-10-15 07:07:50 +00:00
if ( res > = 0 ) {
2003-03-31 07:13:36 +00:00
ast_sched_runq ( sched ) ;
2004-10-15 07:07:50 +00:00
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & monlock ) ;
2003-03-31 07:13:36 +00:00
}
/* Never reached */
return NULL ;
}
static int restart_monitor ( void )
{
/* If we're supposed to be stopped -- stay stopped */
2003-08-14 06:56:11 +00:00
if ( ast_mutex_lock ( & monlock ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Unable to lock monitor \n " ) ;
return - 1 ;
}
2006-09-19 17:07:22 +00:00
if ( monitor_thread = = AST_PTHREADT_STOP ) {
ast_mutex_unlock ( & monlock ) ;
return 0 ;
}
2003-03-31 07:13:36 +00:00
if ( monitor_thread = = pthread_self ( ) ) {
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & monlock ) ;
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Cannot kill myself \n " ) ;
return - 1 ;
}
2004-03-15 09:14:16 +00:00
if ( monitor_thread & & ( monitor_thread ! = AST_PTHREADT_NULL ) ) {
2003-03-31 07:13:36 +00:00
/* Wake up the thread */
pthread_kill ( monitor_thread , SIGURG ) ;
2006-09-19 17:07:22 +00:00
} else {
/* Start a new monitor */
2008-11-04 18:59:48 +00:00
if ( ast_pthread_create_background ( & monitor_thread , NULL , do_monitor , NULL ) < 0 ) {
2006-09-19 17:07:22 +00:00
monitor_thread = AST_PTHREADT_NULL ;
ast_mutex_unlock ( & monlock ) ;
ast_log ( LOG_ERROR , " Unable to start monitor thread. \n " ) ;
return - 1 ;
}
2003-03-31 07:13:36 +00:00
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & monlock ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
2007-10-19 18:01:00 +00:00
static char * handle_cli_h323_set_trace ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
switch ( cmd ) {
case CLI_INIT :
2008-09-28 23:32:14 +00:00
e - > command = " h323 set trace [on|off] " ;
2007-10-19 18:01:00 +00:00
e - > usage =
2008-09-28 23:32:14 +00:00
" Usage: h323 set trace (on|off|<trace level>) \n "
2007-10-19 18:01:00 +00:00
" Enable/Disable H.323 stack tracing for debugging purposes \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
2008-09-28 23:32:14 +00:00
if ( a - > argc ! = e - > args )
2007-10-19 18:01:00 +00:00
return CLI_SHOWUSAGE ;
if ( ! strcasecmp ( a - > argv [ 3 ] , " off " ) ) {
h323_debug ( 0 , 0 ) ;
ast_cli ( a - > fd , " H.323 Trace Disabled \n " ) ;
2008-10-09 17:01:24 +00:00
} else if ( ! strcasecmp ( a - > argv [ 3 ] , " on " ) ) {
h323_debug ( 1 , 1 ) ;
ast_cli ( a - > fd , " H.323 Trace Enabled \n " ) ;
2007-10-19 18:01:00 +00:00
} else {
int tracelevel = atoi ( a - > argv [ 3 ] ) ;
h323_debug ( 1 , tracelevel ) ;
ast_cli ( a - > fd , " H.323 Trace Enabled (Trace Level: %d) \n " , tracelevel ) ;
2004-01-11 02:20:01 +00:00
}
2007-10-19 18:01:00 +00:00
return CLI_SUCCESS ;
2003-03-31 07:13:36 +00:00
}
2007-10-19 18:01:00 +00:00
static char * handle_cli_h323_set_debug ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2003-03-31 07:13:36 +00:00
{
2007-10-19 18:01:00 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-09-28 23:32:14 +00:00
e - > command = " h323 set debug [on|off] " ;
2007-10-19 18:01:00 +00:00
e - > usage =
2008-09-28 23:32:14 +00:00
" Usage: h323 set debug [on|off] \n "
2007-10-19 18:01:00 +00:00
" Enable/Disable H.323 debugging output \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
2008-09-28 23:32:14 +00:00
if ( a - > argc ! = e - > args )
2007-10-19 18:01:00 +00:00
return CLI_SHOWUSAGE ;
2008-09-28 23:32:14 +00:00
if ( strcasecmp ( a - > argv [ 3 ] , " on " ) & & strcasecmp ( a - > argv [ 3 ] , " off " ) )
2007-10-19 18:01:00 +00:00
return CLI_SHOWUSAGE ;
2008-09-28 23:32:14 +00:00
h323debug = ( strcasecmp ( a - > argv [ 3 ] , " on " ) ) ? 0 : 1 ;
2007-10-19 18:01:00 +00:00
ast_cli ( a - > fd , " H.323 Debugging %s \n " , h323debug ? " Enabled " : " Disabled " ) ;
return CLI_SUCCESS ;
2003-03-31 07:13:36 +00:00
}
2007-10-19 18:01:00 +00:00
static char * handle_cli_h323_cycle_gk ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2003-03-31 07:13:36 +00:00
{
2007-10-19 18:01:00 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " h323 cycle gk " ;
e - > usage =
" Usage: h323 cycle gk \n "
" Manually re-register with the Gatekeper (Currently Disabled) \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
2006-09-19 17:07:22 +00:00
}
2007-10-19 18:01:00 +00:00
if ( a - > argc ! = 3 )
return CLI_SHOWUSAGE ;
2003-03-31 07:13:36 +00:00
h323_gk_urq ( ) ;
2006-09-19 17:07:22 +00:00
2003-03-31 07:13:36 +00:00
/* Possibly register with a GK */
2004-01-11 02:20:01 +00:00
if ( ! gatekeeper_disable ) {
2004-01-13 09:24:26 +00:00
if ( h323_set_gk ( gatekeeper_discover , gatekeeper , secret ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Gatekeeper registration failed. \n " ) ;
}
}
2007-10-19 18:01:00 +00:00
return CLI_SUCCESS ;
2003-03-31 07:13:36 +00:00
}
2007-10-19 18:01:00 +00:00
static char * handle_cli_h323_hangup ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2004-01-06 16:51:34 +00:00
{
2007-10-19 18:01:00 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " h323 hangup " ;
e - > usage =
" Usage: h323 hangup <token> \n "
" Manually try to hang up the call identified by <token> \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
2004-01-11 02:20:01 +00:00
}
2007-10-19 18:01:00 +00:00
if ( a - > argc ! = 3 )
return CLI_SHOWUSAGE ;
if ( h323_soft_hangup ( a - > argv [ 2 ] ) ) {
ast_verb ( 3 , " Hangup succeeded on %s \n " , a - > argv [ 2 ] ) ;
2006-09-19 17:07:22 +00:00
} else {
2007-10-19 18:01:00 +00:00
ast_verb ( 3 , " Hangup failed for %s \n " , a - > argv [ 2 ] ) ;
2004-01-06 16:51:34 +00:00
}
2007-10-19 18:01:00 +00:00
return CLI_SUCCESS ;
2004-01-06 16:51:34 +00:00
}
2007-10-19 18:01:00 +00:00
static char * handle_cli_h323_show_tokens ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2004-01-06 16:51:34 +00:00
{
2007-10-19 18:01:00 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " h323 show tokens " ;
e - > usage =
" Usage: h323 show tokens \n "
" Print out all active call tokens \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
2007-10-19 18:01:00 +00:00
if ( a - > argc ! = 3 )
return CLI_SHOWUSAGE ;
2004-01-06 16:51:34 +00:00
2007-10-19 18:01:00 +00:00
h323_show_tokens ( ) ;
2006-09-18 19:54:18 +00:00
2007-10-19 18:01:00 +00:00
return CLI_SUCCESS ;
}
2006-09-22 20:33:47 +00:00
static struct ast_cli_entry cli_h323 [ ] = {
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_cli_h323_set_trace , " Enable/Disable H.323 Stack Tracing " ) ,
AST_CLI_DEFINE ( handle_cli_h323_set_debug , " Enable/Disable H.323 Debugging " ) ,
AST_CLI_DEFINE ( handle_cli_h323_cycle_gk , " Manually re-register with the Gatekeper " ) ,
AST_CLI_DEFINE ( handle_cli_h323_hangup , " Manually try to hang up a call " ) ,
AST_CLI_DEFINE ( handle_cli_h323_show_tokens , " Show all active call tokens " ) ,
2006-09-18 19:54:18 +00:00
} ;
2004-03-20 14:25:39 +00:00
2007-12-13 00:18:04 +00:00
static void delete_users ( void )
{
int pruned = 0 ;
/* Delete all users */
ASTOBJ_CONTAINER_WRLOCK ( & userl ) ;
ASTOBJ_CONTAINER_TRAVERSE ( & userl , 1 , do {
ASTOBJ_RDLOCK ( iterator ) ;
ASTOBJ_MARK ( iterator ) ;
+ + pruned ;
ASTOBJ_UNLOCK ( iterator ) ;
} while ( 0 ) ) ;
if ( pruned ) {
ASTOBJ_CONTAINER_PRUNE_MARKED ( & userl , oh323_destroy_user ) ;
}
ASTOBJ_CONTAINER_UNLOCK ( & userl ) ;
ASTOBJ_CONTAINER_WRLOCK ( & peerl ) ;
ASTOBJ_CONTAINER_TRAVERSE ( & peerl , 1 , do {
ASTOBJ_RDLOCK ( iterator ) ;
ASTOBJ_MARK ( iterator ) ;
ASTOBJ_UNLOCK ( iterator ) ;
} while ( 0 ) ) ;
ASTOBJ_CONTAINER_UNLOCK ( & peerl ) ;
}
static void delete_aliases ( void )
{
int pruned = 0 ;
/* Delete all aliases */
ASTOBJ_CONTAINER_WRLOCK ( & aliasl ) ;
ASTOBJ_CONTAINER_TRAVERSE ( & aliasl , 1 , do {
ASTOBJ_RDLOCK ( iterator ) ;
ASTOBJ_MARK ( iterator ) ;
+ + pruned ;
ASTOBJ_UNLOCK ( iterator ) ;
} while ( 0 ) ) ;
if ( pruned ) {
ASTOBJ_CONTAINER_PRUNE_MARKED ( & aliasl , oh323_destroy_alias ) ;
}
ASTOBJ_CONTAINER_UNLOCK ( & aliasl ) ;
}
static void prune_peers ( void )
{
/* Prune peers who still are supposed to be deleted */
ASTOBJ_CONTAINER_PRUNE_MARKED ( & peerl , oh323_destroy_peer ) ;
}
2006-09-19 17:07:22 +00:00
static int reload_config ( int is_reload )
2005-05-13 20:24:30 +00:00
{
2006-09-19 17:07:22 +00:00
struct ast_config * cfg , * ucfg ;
2003-03-31 07:13:36 +00:00
struct ast_variable * v ;
2006-09-19 17:07:22 +00:00
struct oh323_peer * peer = NULL ;
struct oh323_user * user = NULL ;
2003-03-31 07:13:36 +00:00
struct oh323_alias * alias = NULL ;
2004-04-22 00:20:34 +00:00
struct ast_hostent ahp ; struct hostent * hp ;
2003-03-31 07:13:36 +00:00
char * cat ;
2006-09-22 20:00:31 +00:00
const char * utype ;
2006-09-19 17:07:22 +00:00
int is_user , is_peer , is_alias ;
char _gatekeeper [ 100 ] ;
int gk_discover , gk_disable , gk_changed ;
2007-08-16 21:09:46 +00:00
struct ast_flags config_flags = { is_reload ? CONFIG_FLAG_FILEUNCHANGED : 0 } ;
2006-09-19 17:07:22 +00:00
2007-08-16 21:09:46 +00:00
cfg = ast_config_load ( config , config_flags ) ;
2003-03-31 07:13:36 +00:00
/* We *must* have a config file otherwise stop immediately */
if ( ! cfg ) {
ast_log ( LOG_NOTICE , " Unable to load config %s, H.323 disabled \n " , config ) ;
2003-10-21 13:12:30 +00:00
return 1 ;
2007-08-16 21:09:46 +00:00
} else if ( cfg = = CONFIG_STATUS_FILEUNCHANGED ) {
ucfg = ast_config_load ( " users.conf " , config_flags ) ;
2008-09-12 23:30:03 +00:00
if ( ucfg = = CONFIG_STATUS_FILEUNCHANGED ) {
2007-08-16 21:09:46 +00:00
return 0 ;
2008-09-12 23:30:03 +00:00
} else if ( ucfg = = CONFIG_STATUS_FILEINVALID ) {
ast_log ( LOG_ERROR , " Config file users.conf is in an invalid format. Aborting. \n " ) ;
return 0 ;
}
2007-08-16 21:09:46 +00:00
ast_clear_flag ( & config_flags , CONFIG_FLAG_FILEUNCHANGED ) ;
2008-09-12 23:30:03 +00:00
if ( ( cfg = ast_config_load ( config , config_flags ) ) ) {
ast_log ( LOG_ERROR , " Config file %s is in an invalid format. Aborting. \n " , config ) ;
ast_config_destroy ( ucfg ) ;
return 0 ;
}
} else if ( cfg = = CONFIG_STATUS_FILEINVALID ) {
ast_log ( LOG_ERROR , " Config file %s is in an invalid format. Aborting. \n " , config ) ;
return 0 ;
2007-08-16 21:09:46 +00:00
} else {
ast_clear_flag ( & config_flags , CONFIG_FLAG_FILEUNCHANGED ) ;
2008-09-12 23:30:03 +00:00
if ( ( ucfg = ast_config_load ( " users.conf " , config_flags ) ) = = CONFIG_STATUS_FILEINVALID ) {
ast_log ( LOG_ERROR , " Config file users.conf is in an invalid format. Aborting. \n " ) ;
ast_config_destroy ( cfg ) ;
return 0 ;
}
2003-03-31 07:13:36 +00:00
}
2006-09-19 17:07:22 +00:00
2007-08-18 13:52:44 +00:00
if ( is_reload ) {
delete_users ( ) ;
delete_aliases ( ) ;
prune_peers ( ) ;
}
2006-09-19 17:07:22 +00:00
/* fire up the H.323 Endpoint */
2003-12-18 19:48:42 +00:00
if ( ! h323_end_point_exist ( ) ) {
2006-09-19 17:07:22 +00:00
h323_end_point_create ( ) ;
2003-12-18 19:48:42 +00:00
}
2006-10-25 14:44:50 +00:00
ast_copy_string ( _gatekeeper , gatekeeper , sizeof ( _gatekeeper ) ) ;
2006-09-19 17:07:22 +00:00
gk_discover = gatekeeper_discover ;
gk_disable = gatekeeper_disable ;
2003-03-31 07:13:36 +00:00
memset ( & bindaddr , 0 , sizeof ( bindaddr ) ) ;
2004-12-15 23:24:13 +00:00
memset ( & global_options , 0 , sizeof ( global_options ) ) ;
2006-09-19 17:07:22 +00:00
global_options . fastStart = 1 ;
global_options . h245Tunneling = 1 ;
2006-09-25 09:03:14 +00:00
global_options . dtmfcodec [ 0 ] = H323_DTMF_RFC2833_PT ;
global_options . dtmfcodec [ 1 ] = H323_DTMF_CISCO_PT ;
2006-09-24 18:53:44 +00:00
global_options . dtmfmode = 0 ;
2006-09-28 10:41:38 +00:00
global_options . holdHandling = 0 ;
2006-04-03 18:36:30 +00:00
global_options . capability = GLOBAL_CAPABILITY ;
2005-05-21 17:09:30 +00:00
global_options . bridge = 1 ; /* Do native bridging by default */
2006-10-25 14:44:50 +00:00
strcpy ( default_context , " default " ) ;
2006-09-19 17:07:22 +00:00
h323_signalling_port = 1720 ;
gatekeeper_disable = 1 ;
gatekeeper_discover = 0 ;
gkroute = 0 ;
userbyalias = 1 ;
acceptAnonymous = 1 ;
tos = 0 ;
2007-04-30 16:16:26 +00:00
cos = 0 ;
2006-06-01 16:47:28 +00:00
/* Copy the default jb config over global_jbconf */
memcpy ( & global_jbconf , & default_jbconf , sizeof ( struct ast_jb_conf ) ) ;
2006-09-19 17:07:22 +00:00
if ( ucfg ) {
struct ast_variable * gen ;
int genhas_h323 ;
2006-09-22 20:00:31 +00:00
const char * has_h323 ;
2006-09-19 17:07:22 +00:00
genhas_h323 = ast_true ( ast_variable_retrieve ( ucfg , " general " , " hash323 " ) ) ;
gen = ast_variable_browse ( ucfg , " general " ) ;
for ( cat = ast_category_browse ( ucfg , NULL ) ; cat ; cat = ast_category_browse ( ucfg , cat ) ) {
if ( strcasecmp ( cat , " general " ) ) {
has_h323 = ast_variable_retrieve ( ucfg , cat , " hash323 " ) ;
if ( ast_true ( has_h323 ) | | ( ! has_h323 & & genhas_h323 ) ) {
user = build_user ( cat , gen , ast_variable_browse ( ucfg , cat ) , 0 ) ;
if ( user ) {
ASTOBJ_CONTAINER_LINK ( & userl , user ) ;
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
}
2007-06-25 14:15:05 +00:00
peer = build_peer ( cat , gen , ast_variable_browse ( ucfg , cat ) , 0 ) ;
if ( peer ) {
ASTOBJ_CONTAINER_LINK ( & peerl , peer ) ;
ASTOBJ_UNREF ( peer , oh323_destroy_peer ) ;
}
2006-09-19 17:07:22 +00:00
}
}
2006-06-01 16:47:28 +00:00
}
2006-09-19 17:07:22 +00:00
ast_config_destroy ( ucfg ) ;
}
2006-06-01 16:47:28 +00:00
2006-09-19 17:07:22 +00:00
for ( v = ast_variable_browse ( cfg , " general " ) ; v ; v = v - > next ) {
/* handle jb conf */
if ( ! ast_jb_read_conf ( & global_jbconf , v - > name , v - > value ) )
continue ;
2003-03-31 07:13:36 +00:00
/* Create the interface list */
2003-05-31 18:42:09 +00:00
if ( ! strcasecmp ( v - > name , " port " ) ) {
2004-10-04 10:13:01 +00:00
h323_signalling_port = ( int ) strtol ( v - > value , NULL , 10 ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " bindaddr " ) ) {
2004-04-22 00:20:34 +00:00
if ( ! ( hp = ast_gethostbyname ( v - > value , & ahp ) ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Invalid address: %s \n " , v - > value ) ;
} else {
memcpy ( & bindaddr . sin_addr , hp - > h_addr , sizeof ( bindaddr . sin_addr ) ) ;
}
2007-12-16 10:51:53 +00:00
} else if ( ! strcasecmp ( v - > name , " tos " ) ) { /* Needs to be removed in next release */
ast_log ( LOG_WARNING , " The \" tos \" setting is deprecated in this version of Asterisk. Please change to \" tos_audio \" . \n " ) ;
2007-04-30 16:16:26 +00:00
if ( ast_str2tos ( v - > value , & tos ) ) {
2007-12-16 10:51:53 +00:00
ast_log ( LOG_WARNING , " Invalid tos_audio value at line %d, refer to QoS documentation \n " , v - > lineno ) ;
2007-04-30 16:16:26 +00:00
}
2007-12-16 10:51:53 +00:00
} else if ( ! strcasecmp ( v - > name , " tos_audio " ) ) {
if ( ast_str2tos ( v - > value , & tos ) ) {
ast_log ( LOG_WARNING , " Invalid tos_audio value at line %d, refer to QoS documentation \n " , v - > lineno ) ;
}
} else if ( ! strcasecmp ( v - > name , " cos " ) ) {
ast_log ( LOG_WARNING , " The \" cos \" setting is deprecated in this version of Asterisk. Please change to \" cos_audio \" . \n " ) ;
if ( ast_str2cos ( v - > value , & cos ) ) {
ast_log ( LOG_WARNING , " Invalid cos_audio value at line %d, refer to QoS documentation \n " , v - > lineno ) ;
}
} else if ( ! strcasecmp ( v - > name , " cos_audio " ) ) {
2007-04-30 16:16:26 +00:00
if ( ast_str2cos ( v - > value , & cos ) ) {
2007-12-16 10:51:53 +00:00
ast_log ( LOG_WARNING , " Invalid cos_audio value at line %d, refer to QoS documentation \n " , v - > lineno ) ;
2004-10-22 19:04:02 +00:00
}
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " gatekeeper " ) ) {
if ( ! strcasecmp ( v - > value , " DISABLE " ) ) {
gatekeeper_disable = 1 ;
} else if ( ! strcasecmp ( v - > value , " DISCOVER " ) ) {
gatekeeper_disable = 0 ;
gatekeeper_discover = 1 ;
} else {
gatekeeper_disable = 0 ;
2006-10-25 14:44:50 +00:00
ast_copy_string ( gatekeeper , v - > value , sizeof ( gatekeeper ) ) ;
2003-03-31 07:13:36 +00:00
}
} else if ( ! strcasecmp ( v - > name , " secret " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( secret , v - > value , sizeof ( secret ) ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " AllowGKRouted " ) ) {
2004-10-28 06:06:58 +00:00
gkroute = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " context " ) ) {
2006-10-25 14:44:50 +00:00
ast_copy_string ( default_context , v - > value , sizeof ( default_context ) ) ;
2007-07-26 15:49:18 +00:00
ast_verb ( 2 , " Setting default context to %s \n " , default_context ) ;
2003-12-09 05:14:23 +00:00
} else if ( ! strcasecmp ( v - > name , " UserByAlias " ) ) {
2005-05-02 18:46:36 +00:00
userbyalias = ast_true ( v - > value ) ;
2006-09-19 17:07:22 +00:00
} else if ( ! strcasecmp ( v - > name , " AcceptAnonymous " ) ) {
acceptAnonymous = ast_true ( v - > value ) ;
2005-05-21 17:09:30 +00:00
} else if ( ! update_common_options ( v , & global_options ) ) {
/* dummy */
2004-07-17 19:38:30 +00:00
}
2003-03-31 07:13:36 +00:00
}
2006-09-24 18:53:44 +00:00
if ( ! global_options . dtmfmode )
global_options . dtmfmode = H323_DTMF_RFC2833 ;
2006-09-28 10:41:38 +00:00
if ( global_options . holdHandling = = ~ 0 )
global_options . holdHandling = 0 ;
else if ( ! global_options . holdHandling )
global_options . holdHandling = H323_HOLD_H450 ;
2006-09-19 17:07:22 +00:00
for ( cat = ast_category_browse ( cfg , NULL ) ; cat ; cat = ast_category_browse ( cfg , cat ) ) {
2003-03-31 07:13:36 +00:00
if ( strcasecmp ( cat , " general " ) ) {
utype = ast_variable_retrieve ( cfg , cat , " type " ) ;
if ( utype ) {
2006-09-19 17:07:22 +00:00
is_user = is_peer = is_alias = 0 ;
if ( ! strcasecmp ( utype , " user " ) )
is_user = 1 ;
else if ( ! strcasecmp ( utype , " peer " ) )
is_peer = 1 ;
else if ( ! strcasecmp ( utype , " friend " ) )
is_user = is_peer = 1 ;
else if ( ! strcasecmp ( utype , " h323 " ) | | ! strcasecmp ( utype , " alias " ) )
is_alias = 1 ;
else {
ast_log ( LOG_WARNING , " Unknown type '%s' for '%s' in %s \n " , utype , cat , config ) ;
continue ;
}
if ( is_user ) {
user = build_user ( cat , ast_variable_browse ( cfg , cat ) , NULL , 0 ) ;
2005-05-02 18:46:36 +00:00
if ( user ) {
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_LINK ( & userl , user ) ;
ASTOBJ_UNREF ( user , oh323_destroy_user ) ;
2005-05-02 18:46:36 +00:00
}
2006-09-19 17:07:22 +00:00
}
if ( is_peer ) {
peer = build_peer ( cat , ast_variable_browse ( cfg , cat ) , NULL , 0 ) ;
2003-03-31 07:13:36 +00:00
if ( peer ) {
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_LINK ( & peerl , peer ) ;
ASTOBJ_UNREF ( peer , oh323_destroy_peer ) ;
2003-03-31 07:13:36 +00:00
}
2006-09-19 17:07:22 +00:00
}
if ( is_alias ) {
alias = build_alias ( cat , ast_variable_browse ( cfg , cat ) , NULL , 0 ) ;
2003-03-31 07:13:36 +00:00
if ( alias ) {
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_LINK ( & aliasl , alias ) ;
ASTOBJ_UNREF ( alias , oh323_destroy_alias ) ;
2003-03-31 07:13:36 +00:00
}
}
2004-10-28 06:06:58 +00:00
} else {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Section '%s' lacks type \n " , cat ) ;
2004-10-28 06:06:58 +00:00
}
2003-03-31 07:13:36 +00:00
}
}
2005-01-25 06:10:20 +00:00
ast_config_destroy ( cfg ) ;
2003-03-31 07:13:36 +00:00
/* Register our H.323 aliases if any*/
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_WRLOCK ( & aliasl ) ;
ASTOBJ_CONTAINER_TRAVERSE ( & aliasl , 1 , do {
ASTOBJ_RDLOCK ( iterator ) ;
if ( h323_set_alias ( iterator ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Alias %s rejected by endpoint \n " , alias - > name ) ;
2006-09-19 17:07:22 +00:00
ASTOBJ_UNLOCK ( iterator ) ;
continue ;
}
ASTOBJ_UNLOCK ( iterator ) ;
} while ( 0 ) ) ;
ASTOBJ_CONTAINER_UNLOCK ( & aliasl ) ;
/* Don't touch GK if nothing changed because URQ will drop all existing calls */
gk_changed = 0 ;
if ( gatekeeper_disable ! = gk_disable )
gk_changed = is_reload ;
else if ( ! gatekeeper_disable & & ( gatekeeper_discover ! = gk_discover ) )
gk_changed = is_reload ;
else if ( ! gatekeeper_disable & & ( strncmp ( _gatekeeper , gatekeeper , sizeof ( _gatekeeper ) ) ! = 0 ) )
gk_changed = is_reload ;
if ( gk_changed ) {
if ( ! gk_disable )
h323_gk_urq ( ) ;
if ( ! gatekeeper_disable ) {
if ( h323_set_gk ( gatekeeper_discover , gatekeeper , secret ) ) {
ast_log ( LOG_ERROR , " Gatekeeper registration failed. \n " ) ;
gatekeeper_disable = 1 ;
}
}
2003-03-31 07:13:36 +00:00
}
return 0 ;
}
2007-10-19 18:01:00 +00:00
static int h323_reload ( void )
2004-10-15 07:07:50 +00:00
{
ast_mutex_lock ( & h323_reload_lock ) ;
2005-05-13 20:24:30 +00:00
if ( h323_reloading ) {
ast_verbose ( " Previous H.323 reload not yet done \n " ) ;
} else {
h323_reloading = 1 ;
}
2004-10-15 07:07:50 +00:00
ast_mutex_unlock ( & h323_reload_lock ) ;
2005-05-13 20:24:30 +00:00
restart_monitor ( ) ;
return 0 ;
2004-10-15 07:07:50 +00:00
}
2007-10-19 18:01:00 +00:00
static char * handle_cli_h323_reload ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
switch ( cmd ) {
case CLI_INIT :
e - > command = " h323 reload " ;
e - > usage =
" Usage: h323 reload \n "
" Reloads H.323 configuration from h323.conf \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
if ( a - > argc ! = 2 )
return CLI_SHOWUSAGE ;
h323_reload ( ) ;
return CLI_SUCCESS ;
}
2004-10-15 07:07:50 +00:00
static int h323_do_reload ( void )
2003-03-31 07:13:36 +00:00
{
2006-09-19 17:07:22 +00:00
reload_config ( 1 ) ;
2005-05-13 20:24:30 +00:00
return 0 ;
2004-10-15 07:07:50 +00:00
}
2003-03-31 07:13:36 +00:00
2006-09-19 17:07:22 +00:00
static int reload ( void )
2004-10-15 07:07:50 +00:00
{
2007-07-18 15:26:52 +00:00
if ( ! sched | | ! io ) {
ast_log ( LOG_NOTICE , " Unload and load chan_h323.so again in order to receive configuration changes. \n " ) ;
return 0 ;
}
2007-10-19 18:01:00 +00:00
return h323_reload ( ) ;
2003-03-31 07:13:36 +00:00
}
2006-09-22 20:33:47 +00:00
static struct ast_cli_entry cli_h323_reload =
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_cli_h323_reload , " Reload H.323 configuration " ) ;
2006-09-22 20:33:47 +00:00
2006-09-19 17:07:22 +00:00
static enum ast_rtp_get_result oh323_get_rtp_peer ( struct ast_channel * chan , struct ast_rtp * * rtp )
2003-03-31 07:13:36 +00:00
{
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2008-02-20 22:29:47 +00:00
enum ast_rtp_get_result res = AST_RTP_TRY_PARTIAL ;
2006-09-19 17:07:22 +00:00
if ( ! ( pvt = ( struct oh323_pvt * ) chan - > tech_pvt ) )
2008-02-20 22:29:47 +00:00
return AST_RTP_GET_FAILED ;
2006-09-19 17:07:22 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2008-04-09 18:05:40 +00:00
* rtp = pvt - > rtp ;
#if 0
if ( pvt - > options . bridge ) {
2006-09-19 17:07:22 +00:00
res = AST_RTP_TRY_NATIVE ;
2003-08-25 09:54:36 +00:00
}
2008-04-09 18:05:40 +00:00
# endif
2006-09-19 17:07:22 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
return res ;
2003-03-31 07:13:36 +00:00
}
2006-09-19 17:07:22 +00:00
static enum ast_rtp_get_result oh323_get_vrtp_peer ( struct ast_channel * chan , struct ast_rtp * * rtp )
2003-03-31 07:13:36 +00:00
{
2006-09-19 17:07:22 +00:00
return AST_RTP_GET_FAILED ;
2003-07-01 19:11:37 +00:00
}
2003-08-25 09:54:36 +00:00
static char * convertcap ( int cap )
{
switch ( cap ) {
case AST_FORMAT_G723_1 :
return " G.723 " ;
case AST_FORMAT_GSM :
return " GSM " ;
case AST_FORMAT_ULAW :
return " ULAW " ;
case AST_FORMAT_ALAW :
return " ALAW " ;
2006-10-25 00:32:23 +00:00
case AST_FORMAT_G722 :
return " G.722 " ;
2003-08-25 09:54:36 +00:00
case AST_FORMAT_ADPCM :
return " G.728 " ;
case AST_FORMAT_G729A :
return " G.729 " ;
case AST_FORMAT_SPEEX :
return " SPEEX " ;
case AST_FORMAT_ILBC :
return " ILBC " ;
default :
ast_log ( LOG_NOTICE , " Don't know how to deal with mode %d \n " , cap ) ;
return NULL ;
}
}
2007-02-18 19:09:29 +00:00
static int oh323_set_rtp_peer ( struct ast_channel * chan , struct ast_rtp * rtp , struct ast_rtp * vrtp , struct ast_rtp * trtp , int codecs , int nat_active )
2003-07-01 19:11:37 +00:00
{
/* XXX Deal with Video */
2005-05-11 13:27:49 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
struct sockaddr_in them ;
struct sockaddr_in us ;
2003-08-25 09:54:36 +00:00
char * mode ;
2003-08-14 08:02:33 +00:00
if ( ! rtp ) {
2003-03-31 07:13:36 +00:00
return 0 ;
2003-08-14 08:02:33 +00:00
}
2003-08-25 09:54:36 +00:00
2006-09-19 17:07:22 +00:00
mode = convertcap ( chan - > writeformat ) ;
2005-05-11 13:27:49 +00:00
pvt = ( struct oh323_pvt * ) chan - > tech_pvt ;
if ( ! pvt ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " No Private Structure, this is bad \n " ) ;
return - 1 ;
}
2006-09-19 17:07:22 +00:00
ast_rtp_get_peer ( rtp , & them ) ;
2003-08-25 09:54:36 +00:00
ast_rtp_get_us ( rtp , & us ) ;
2006-09-19 17:07:22 +00:00
#if 0 /* Native bridge still isn't ready */
h323_native_bridge ( pvt - > cd . call_token , ast_inet_ntoa ( them . sin_addr ) , mode ) ;
# endif
2003-03-31 07:13:36 +00:00
return 0 ;
}
static struct ast_rtp_protocol oh323_rtp = {
2006-04-03 18:36:30 +00:00
. type = " H323 " ,
2005-03-04 06:47:24 +00:00
. get_rtp_info = oh323_get_rtp_peer ,
. get_vrtp_info = oh323_get_vrtp_peer ,
2006-09-19 17:07:22 +00:00
. set_rtp_peer = oh323_set_rtp_peer ,
2003-03-31 07:13:36 +00:00
} ;
2006-09-19 17:07:22 +00:00
static enum ast_module_load_result load_module ( void )
2003-03-31 07:13:36 +00:00
{
int res ;
2006-09-19 17:07:22 +00:00
h323debug = 0 ;
2004-10-15 07:07:50 +00:00
sched = sched_context_create ( ) ;
if ( ! sched ) {
ast_log ( LOG_WARNING , " Unable to create schedule context \n " ) ;
2006-09-19 17:07:22 +00:00
return AST_MODULE_LOAD_FAILURE ;
2004-10-15 07:07:50 +00:00
}
io = io_context_create ( ) ;
if ( ! io ) {
ast_log ( LOG_WARNING , " Unable to create I/O context \n " ) ;
2006-09-19 17:07:22 +00:00
return AST_MODULE_LOAD_FAILURE ;
2004-10-15 07:07:50 +00:00
}
2006-09-19 17:07:22 +00:00
ast_cli_register ( & cli_h323_reload ) ;
ASTOBJ_CONTAINER_INIT ( & userl ) ;
ASTOBJ_CONTAINER_INIT ( & peerl ) ;
ASTOBJ_CONTAINER_INIT ( & aliasl ) ;
res = reload_config ( 0 ) ;
2003-12-10 23:34:47 +00:00
if ( res ) {
2007-01-23 06:56:26 +00:00
/* No config entry */
ast_log ( LOG_NOTICE , " Unload and load chan_h323.so again in order to receive configuration changes. \n " ) ;
2006-09-20 16:24:00 +00:00
ast_cli_unregister ( & cli_h323_reload ) ;
io_context_destroy ( io ) ;
2007-01-23 06:56:26 +00:00
io = NULL ;
2006-09-20 16:24:00 +00:00
sched_context_destroy ( sched ) ;
2007-01-23 06:56:26 +00:00
sched = NULL ;
2006-09-20 16:24:00 +00:00
ASTOBJ_CONTAINER_DESTROY ( & userl ) ;
ASTOBJ_CONTAINER_DESTROY ( & peerl ) ;
ASTOBJ_CONTAINER_DESTROY ( & aliasl ) ;
2007-01-23 06:56:26 +00:00
return AST_MODULE_LOAD_DECLINE ;
2003-12-10 23:34:47 +00:00
} else {
/* Make sure we can register our channel type */
2005-03-04 06:47:24 +00:00
if ( ast_channel_register ( & oh323_tech ) ) {
2006-04-03 18:36:30 +00:00
ast_log ( LOG_ERROR , " Unable to register channel class 'H323' \n " ) ;
2006-09-19 17:07:22 +00:00
ast_cli_unregister ( & cli_h323_reload ) ;
2003-03-31 07:13:36 +00:00
h323_end_process ( ) ;
2006-09-19 17:07:22 +00:00
io_context_destroy ( io ) ;
sched_context_destroy ( sched ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & userl , oh323_destroy_user ) ;
ASTOBJ_CONTAINER_DESTROY ( & userl ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & peerl , oh323_destroy_peer ) ;
ASTOBJ_CONTAINER_DESTROY ( & peerl ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & aliasl , oh323_destroy_alias ) ;
ASTOBJ_CONTAINER_DESTROY ( & aliasl ) ;
return AST_MODULE_LOAD_FAILURE ;
2003-03-31 07:13:36 +00:00
}
2006-09-18 19:54:18 +00:00
ast_cli_register_multiple ( cli_h323 , sizeof ( cli_h323 ) / sizeof ( struct ast_cli_entry ) ) ;
2004-03-20 14:25:39 +00:00
2003-03-31 07:13:36 +00:00
ast_rtp_proto_register ( & oh323_rtp ) ;
/* Register our callback functions */
2006-09-19 17:07:22 +00:00
h323_callback_register ( setup_incoming_call ,
setup_outgoing_call ,
external_rtp_create ,
setup_rtp_connection ,
cleanup_connection ,
2005-05-11 13:27:49 +00:00
chan_ringing ,
2006-09-19 17:07:22 +00:00
connection_made ,
receive_digit ,
2005-05-11 13:27:49 +00:00
answer_call ,
progress ,
set_dtmf_payload ,
2005-05-19 19:13:19 +00:00
hangup_connection ,
2006-09-19 17:07:22 +00:00
set_local_capabilities ,
2006-09-28 10:41:38 +00:00
set_peer_capabilities ,
remote_hold ) ;
2003-03-31 07:13:36 +00:00
/* start the h.323 listener */
2004-10-04 10:13:01 +00:00
if ( h323_start_listener ( h323_signalling_port , bindaddr ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Unable to create H323 listener. \n " ) ;
2006-09-19 17:07:22 +00:00
ast_rtp_proto_unregister ( & oh323_rtp ) ;
ast_cli_unregister_multiple ( cli_h323 , sizeof ( cli_h323 ) / sizeof ( struct ast_cli_entry ) ) ;
ast_cli_unregister ( & cli_h323_reload ) ;
h323_end_process ( ) ;
io_context_destroy ( io ) ;
sched_context_destroy ( sched ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & userl , oh323_destroy_user ) ;
ASTOBJ_CONTAINER_DESTROY ( & userl ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & peerl , oh323_destroy_peer ) ;
ASTOBJ_CONTAINER_DESTROY ( & peerl ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & aliasl , oh323_destroy_alias ) ;
ASTOBJ_CONTAINER_DESTROY ( & aliasl ) ;
return AST_MODULE_LOAD_FAILURE ;
2003-03-31 07:13:36 +00:00
}
/* Possibly register with a GK */
2004-10-28 06:06:58 +00:00
if ( ! gatekeeper_disable ) {
2003-03-31 07:13:36 +00:00
if ( h323_set_gk ( gatekeeper_discover , gatekeeper , secret ) ) {
ast_log ( LOG_ERROR , " Gatekeeper registration failed. \n " ) ;
2006-09-19 17:07:22 +00:00
gatekeeper_disable = 1 ;
2006-09-20 16:24:00 +00:00
res = AST_MODULE_LOAD_SUCCESS ;
2003-03-31 07:13:36 +00:00
}
}
/* And start the monitor for the first time */
restart_monitor ( ) ;
}
return res ;
}
2004-01-11 02:20:01 +00:00
2006-09-19 17:07:22 +00:00
static int unload_module ( void )
2003-03-31 07:13:36 +00:00
{
struct oh323_pvt * p , * pl ;
2004-10-22 19:04:02 +00:00
/* unregister commands */
2006-09-18 19:54:18 +00:00
ast_cli_unregister_multiple ( cli_h323 , sizeof ( cli_h323 ) / sizeof ( struct ast_cli_entry ) ) ;
2006-09-19 17:07:22 +00:00
ast_cli_unregister ( & cli_h323_reload ) ;
2005-03-04 06:47:24 +00:00
ast_channel_unregister ( & oh323_tech ) ;
2006-09-19 17:07:22 +00:00
ast_rtp_proto_unregister ( & oh323_rtp ) ;
2003-08-14 06:56:11 +00:00
if ( ! ast_mutex_lock ( & iflock ) ) {
2004-10-22 19:04:02 +00:00
/* hangup all interfaces if they have an owner */
p = iflist ;
while ( p ) {
if ( p - > owner ) {
ast_softhangup ( p - > owner , AST_SOFTHANGUP_APPUNLOAD ) ;
}
p = p - > next ;
}
iflist = NULL ;
ast_mutex_unlock ( & iflock ) ;
2003-03-31 07:13:36 +00:00
} else {
ast_log ( LOG_WARNING , " Unable to lock the interface list \n " ) ;
return - 1 ;
}
2004-01-13 03:07:15 +00:00
if ( ! ast_mutex_lock ( & monlock ) ) {
2006-09-19 17:07:22 +00:00
if ( ( monitor_thread ! = AST_PTHREADT_STOP ) & & ( monitor_thread ! = AST_PTHREADT_NULL ) ) {
2008-10-30 20:35:46 +00:00
if ( monitor_thread ! = pthread_self ( ) ) {
2006-09-19 17:07:22 +00:00
pthread_cancel ( monitor_thread ) ;
2008-10-30 20:35:46 +00:00
}
2005-05-11 13:27:49 +00:00
pthread_kill ( monitor_thread , SIGURG ) ;
2008-11-04 18:59:48 +00:00
pthread_join ( monitor_thread , NULL ) ;
2005-05-11 13:27:49 +00:00
}
monitor_thread = AST_PTHREADT_STOP ;
ast_mutex_unlock ( & monlock ) ;
} else {
ast_log ( LOG_WARNING , " Unable to lock the monitor \n " ) ;
return - 1 ;
}
2003-08-14 06:56:11 +00:00
if ( ! ast_mutex_lock ( & iflock ) ) {
2003-03-31 07:13:36 +00:00
/* destroy all the interfaces and free their memory */
p = iflist ;
while ( p ) {
pl = p ;
p = p - > next ;
/* free associated memory */
2004-06-22 17:42:14 +00:00
ast_mutex_destroy ( & pl - > lock ) ;
2007-06-03 06:10:27 +00:00
ast_free ( pl ) ;
2003-03-31 07:13:36 +00:00
}
iflist = NULL ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & iflock ) ;
2003-03-31 07:13:36 +00:00
} else {
ast_log ( LOG_WARNING , " Unable to lock the interface list \n " ) ;
return - 1 ;
}
2006-09-19 17:07:22 +00:00
if ( ! gatekeeper_disable )
h323_gk_urq ( ) ;
2003-03-31 07:13:36 +00:00
h323_end_process ( ) ;
2007-01-23 06:56:26 +00:00
if ( io )
io_context_destroy ( io ) ;
if ( sched )
sched_context_destroy ( sched ) ;
2006-09-19 17:07:22 +00:00
ASTOBJ_CONTAINER_DESTROYALL ( & userl , oh323_destroy_user ) ;
ASTOBJ_CONTAINER_DESTROY ( & userl ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & peerl , oh323_destroy_peer ) ;
ASTOBJ_CONTAINER_DESTROY ( & peerl ) ;
ASTOBJ_CONTAINER_DESTROYALL ( & aliasl , oh323_destroy_alias ) ;
ASTOBJ_CONTAINER_DESTROY ( & aliasl ) ;
return 0 ;
}
2003-03-31 07:13:36 +00:00
2006-08-21 02:11:39 +00:00
AST_MODULE_INFO ( ASTERISK_GPL_KEY , AST_MODFLAG_DEFAULT , " The NuFone Network's OpenH323 Channel Driver " ,
. load = load_module ,
. unload = unload_module ,
. reload = reload ,
2006-09-19 17:07:22 +00:00
) ;