2003-03-31 07:13:36 +00:00
/*
2003-06-20 06:03:34 +00:00
* chan_h323 . c
2003-03-31 07:13:36 +00:00
*
* OpenH323 Channel Driver for ASTERISK PBX .
* By Jeremy McNamara
* For The NuFone Network
*
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
*
* This file is part of the chan_h323 driver for Asterisk
*
* chan_h323 is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* chan_h323 is distributed WITHOUT ANY WARRANTY ; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE . See the GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*
2003-08-25 09:54:36 +00:00
* Version Info : $ Id $
2003-03-31 07:13:36 +00:00
*/
2004-06-26 03:50:14 +00:00
# include <sys/socket.h>
# include <sys/signal.h>
# include <sys/param.h>
# if defined(BSD)
# ifndef IPTOS_MINCOST
# define IPTOS_MINCOST 0x02
# endif
# endif
# include <arpa/inet.h>
# include <net/if.h>
# include <netinet/in.h>
# include <netinet/in_systm.h>
# include <netinet/ip.h>
# include <unistd.h>
# include <stdlib.h>
# include <netdb.h>
2003-03-31 07:13:36 +00:00
# include <stdio.h>
# include <string.h>
2004-06-26 03:50:14 +00:00
# include <errno.h>
# include <fcntl.h>
# ifdef __cplusplus
extern " C " {
# endif
2003-03-31 07:13:36 +00:00
# include <asterisk/lock.h>
# include <asterisk/logger.h>
# include <asterisk/channel.h>
# include <asterisk/config.h>
# include <asterisk/module.h>
# include <asterisk/pbx.h>
# include <asterisk/options.h>
2004-05-03 22:19:03 +00:00
# include <asterisk/utils.h>
2003-03-31 07:13:36 +00:00
# include <asterisk/lock.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>
2004-10-26 22:25:43 +00:00
# include <asterisk/causes.h>
2004-06-26 03:50:14 +00:00
# ifdef __cplusplus
}
2004-04-19 08:11:51 +00:00
# endif
2003-08-16 17:00:22 +00:00
# include "h323/chan_h323.h"
2003-03-31 07:13:36 +00:00
2004-09-30 19:36:46 +00:00
send_digit_cb on_send_digit ;
2004-10-10 12:20:18 +00:00
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 ;
setup_outbound_cb on_outgoing_call ;
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 ;
2004-09-30 19:36:46 +00:00
/* global debug flag */
2004-06-26 03:50:14 +00:00
int h323debug ;
2004-09-30 19:36:46 +00:00
/** Variables required by Asterisk */
2005-03-04 06:47:24 +00:00
static const char type [ ] = " H323 " ;
static const char desc [ ] = " The NuFone Network's Open H.323 Channel Driver " ;
static const char tdesc [ ] = " The NuFone Network's Open H.323 Channel Driver " ;
static const char config [ ] = " h323.conf " ;
2004-09-30 19:36:46 +00:00
static char default_context [ AST_MAX_EXTENSION ] = " default " ;
2004-12-15 23:24:13 +00:00
static struct sockaddr_in bindaddr ;
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 ;
2004-10-01 04:50:34 +00:00
static int usingGk = 0 ;
2004-09-30 19:36:46 +00:00
static int gkroute = 0 ;
/* Assume we can native bridge by default */
static int bridging = 1 ;
/* 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 ;
2003-03-31 07:13:36 +00:00
static int capability = AST_FORMAT_ULAW ;
static int tos = 0 ;
static int dtmfmode = H323_DTMF_RFC2833 ;
static char secret [ 50 ] ;
2004-12-15 23:24:13 +00:00
static call_options_t global_options ;
2003-03-31 07:13:36 +00:00
/** Private structure of a OpenH323 channel */
struct oh323_pvt {
2003-08-14 06:56:11 +00:00
ast_mutex_t lock ; /* Channel private lock */
2004-10-04 10:13:01 +00:00
call_options_t options ; /* Options to be used during call setup */
2004-05-18 10:33:46 +00:00
int alreadygone ; /* Whether or not we've already been destroyed by our peer */
2004-04-05 20:45:14 +00:00
int needdestroy ; /* if we need to be destroyed */
call_details_t cd ; /* Call details */
2003-03-31 07:13:36 +00:00
struct ast_channel * owner ; /* Who owns us */
2004-10-04 10:13:01 +00:00
struct sockaddr_in sa ; /* Our peer */
struct sockaddr_in redirip ; /* Where our RTP should be going if not to us */
2004-04-05 20:45:14 +00:00
int capability ; /* audio capability */
int nonCodecCapability ; /* non-audio capability */
int outgoing ; /* Outgoing or incoming call? */
int nat ; /* Are we talking to a NAT EP?*/
int bridge ; /* Determine of we should native bridge or not*/
char exten [ AST_MAX_EXTENSION ] ; /* Requested extension */
char context [ AST_MAX_EXTENSION ] ; /* Context where to start */
2003-03-31 07:13:36 +00:00
char accountcode [ 256 ] ; /* Account code */
2004-12-16 02:03:19 +00:00
char cid_num [ 80 ] ; /* Caller*id number, if available */
char cid_name [ 80 ] ; /* Caller*id name, if available */
char rdnis [ 80 ] ; /* Referring DNIS, if available */
2004-04-05 20:45:14 +00:00
int amaflags ; /* AMA Flags */
2003-03-31 07:13:36 +00:00
struct ast_rtp * rtp ; /* RTP Session */
2004-04-05 20:45:14 +00:00
int dtmfmode ; /* What DTMF Mode is being used */
2003-03-31 07:13:36 +00:00
struct ast_dsp * vad ; /* Used for in-band DTMF detection */
2005-04-04 15:54:34 +00:00
int nativeformats ; /* Codec formats supported by a channel */
int needhangup ; /* Send hangup when Asterisk is ready */
int hangupcause ; /* Hangup cause from OpenH323 layer */
2003-03-31 07:13:36 +00:00
struct oh323_pvt * next ; /* Next channel in list */
} * iflist = NULL ;
static struct ast_user_list {
struct oh323_user * users ;
2003-08-14 06:56:11 +00:00
ast_mutex_t lock ;
2004-06-12 03:44:51 +00:00
} userl ;
2003-03-31 07:13:36 +00:00
static struct ast_peer_list {
struct oh323_peer * peers ;
2003-08-14 06:56:11 +00:00
ast_mutex_t lock ;
2004-06-12 03:44:51 +00:00
} peerl ;
2003-03-31 07:13:36 +00:00
static struct ast_alias_list {
struct oh323_alias * aliases ;
2003-08-14 06:56:11 +00:00
ast_mutex_t lock ;
2004-06-12 03:44:51 +00:00
} aliasl ;
2003-03-31 07:13:36 +00:00
2004-09-30 19:36:46 +00:00
/** Asterisk RTP stuff */
2003-03-31 07:13:36 +00:00
static struct sched_context * sched ;
static struct io_context * io ;
2004-09-30 19:36:46 +00:00
/** Protect the interface list (oh323_pvt) */
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( iflock ) ;
2003-03-31 07:13:36 +00:00
/** Usage counter and associated lock */
2004-10-22 19:04:02 +00:00
static int usecnt = 0 ;
2004-06-09 01:45:08 +00:00
AST_MUTEX_DEFINE_STATIC ( usecnt_lock ) ;
2003-03-31 07:13:36 +00:00
/* Protect the monitoring thread, so only one process can kill or start it, and not
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
2004-09-30 19:36:46 +00:00
/* 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 ) ;
2004-10-15 07:07:50 +00:00
/* Protect the reload process */
AST_MUTEX_DEFINE_STATIC ( h323_reload_lock ) ;
static int h323_reloading = 0 ;
2003-03-31 07:13:36 +00:00
/* This is the thread for the monitor which checks for input on the channels
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
2005-03-04 06:47:24 +00:00
static struct ast_channel * oh323_request ( const char * type , int format , void * data , int * cause ) ;
static int oh323_digit ( struct ast_channel * c , char digit ) ;
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 ) ;
static int oh323_indicate ( struct ast_channel * c , int condition ) ;
static int oh323_fixup ( struct ast_channel * oldchan , struct ast_channel * newchan ) ;
static const struct ast_channel_tech oh323_tech = {
. type = type ,
. description = tdesc ,
. capabilities = AST_FORMAT_ULAW ,
2005-03-17 21:30:19 +00:00
. properties = AST_CHAN_TP_WANTSJITTER ,
2005-03-04 06:47:24 +00:00
. requester = oh323_request ,
. send_digit = oh323_digit ,
. call = oh323_call ,
. hangup = oh323_hangup ,
. answer = oh323_answer ,
. read = oh323_read ,
. write = oh323_write ,
. indicate = oh323_indicate ,
. fixup = oh323_fixup ,
/* disable, for now */
#if 0
. bridge = ast_rtp_bridge ,
# endif
} ;
2005-04-04 15:54:34 +00:00
static void oh323_update_info ( struct ast_channel * c )
{
struct oh323_pvt * pvt = c - > tech_pvt ;
ast_mutex_lock ( & pvt - > lock ) ;
if ( c - > nativeformats ! = pvt - > nativeformats ) {
if ( h323debug )
ast_log ( LOG_DEBUG , " Preparing %s for new native format \n " , c - > name ) ;
c - > nativeformats = pvt - > nativeformats ;
ast_set_read_format ( c , c - > readformat ) ;
ast_set_write_format ( c , c - > writeformat ) ;
}
if ( pvt - > needhangup ) {
if ( h323debug )
ast_log ( LOG_DEBUG , " Process pending hangup for %s \n " , c - > name ) ;
c - > _softhangup | = AST_SOFTHANGUP_DEV ;
c - > hangupcause = pvt - > hangupcause ;
ast_queue_hangup ( c ) ;
pvt - > needhangup = 0 ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
}
static void cleanup_call_details ( call_details_t * cd )
{
if ( cd - > call_token ) {
free ( cd - > call_token ) ;
cd - > call_token = NULL ;
}
if ( cd - > call_source_aliases ) {
free ( cd - > call_source_aliases ) ;
cd - > call_source_aliases = NULL ;
}
if ( cd - > call_dest_alias ) {
free ( cd - > call_dest_alias ) ;
cd - > call_dest_alias = NULL ;
}
if ( cd - > call_source_name ) {
free ( cd - > call_source_name ) ;
cd - > call_source_name = NULL ;
}
if ( cd - > call_source_e164 ) {
free ( cd - > call_source_e164 ) ;
cd - > call_source_e164 = NULL ;
}
if ( cd - > call_dest_e164 ) {
free ( cd - > call_dest_e164 ) ;
cd - > call_dest_e164 = NULL ;
}
if ( cd - > sourceIp ) {
free ( cd - > sourceIp ) ;
cd - > sourceIp = NULL ;
}
}
2003-03-31 07:13:36 +00:00
static void __oh323_destroy ( struct oh323_pvt * p )
{
struct oh323_pvt * cur , * prev = NULL ;
if ( p - > rtp ) {
ast_rtp_destroy ( p - > rtp ) ;
}
2005-04-04 15:54:34 +00:00
/* Free dsp used for in-band DTMF detection */
if ( p - > vad ) {
ast_dsp_free ( p - > vad ) ;
}
cleanup_call_details ( & p - > cd ) ;
2003-03-31 07:13:36 +00:00
/* Unlink us from the owner if we have one */
if ( p - > owner ) {
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & p - > owner - > lock ) ;
2003-03-31 07:13:36 +00:00
ast_log ( LOG_DEBUG , " Detaching from %s \n " , p - > owner - > name ) ;
2005-03-04 06:47:24 +00:00
p - > owner - > tech_pvt = NULL ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & p - > owner - > lock ) ;
2003-03-31 07:13:36 +00:00
}
cur = iflist ;
while ( cur ) {
if ( cur = = p ) {
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 {
ast_mutex_destroy ( & p - > lock ) ;
2003-03-31 07:13:36 +00:00
free ( p ) ;
2004-06-22 17:42:14 +00:00
}
2003-03-31 07:13:36 +00:00
}
static void oh323_destroy ( struct oh323_pvt * p )
{
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & iflock ) ;
2003-03-31 07:13:36 +00:00
__oh323_destroy ( p ) ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & iflock ) ;
2003-03-31 07:13:36 +00:00
}
static struct oh323_alias * build_alias ( char * name , struct ast_variable * v )
{
struct oh323_alias * alias ;
alias = ( struct oh323_alias * ) malloc ( sizeof ( struct oh323_alias ) ) ;
if ( alias ) {
memset ( alias , 0 , sizeof ( struct oh323_alias ) ) ;
2004-10-04 10:13:01 +00:00
strncpy ( alias - > name , name , sizeof ( alias - > name ) - 1 ) ;
2003-03-31 07:13:36 +00:00
while ( v ) {
if ( ! strcasecmp ( v - > name , " e164 " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( alias - > e164 , v - > value , sizeof ( alias - > e164 ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " prefix " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( alias - > prefix , v - > value , sizeof ( alias - > prefix ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " context " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( alias - > context , v - > value , sizeof ( alias - > context ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " secret " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( alias - > secret , v - > value , sizeof ( alias - > secret ) - 1 ) ;
2003-12-03 20:08:58 +00:00
} else {
2003-12-18 19:48:42 +00:00
if ( strcasecmp ( v - > value , " h323 " ) ) {
2003-12-03 20:08:58 +00:00
ast_log ( LOG_WARNING , " Keyword %s does not make sense in type=h323 \n " , v - > value ) ;
2003-12-18 18:24:36 +00:00
}
2003-03-31 07:13:36 +00:00
}
v = v - > next ;
}
}
return alias ;
}
static struct oh323_user * build_user ( char * name , struct ast_variable * v )
{
struct oh323_user * user ;
int format ;
user = ( struct oh323_user * ) malloc ( sizeof ( struct oh323_user ) ) ;
if ( user ) {
memset ( user , 0 , sizeof ( struct oh323_user ) ) ;
2004-10-04 10:13:01 +00:00
strncpy ( user - > name , name , sizeof ( user - > name ) - 1 ) ;
2004-12-15 23:24:13 +00:00
user - > options . dtmfcodec = 101 ;
2004-10-28 06:06:58 +00:00
/* set a native brigding default value */
2004-09-30 19:36:46 +00:00
user - > bridge = bridging ;
2004-10-28 06:06:58 +00:00
/* and default context */
2004-10-04 10:13:01 +00:00
strncpy ( user - > context , default_context , sizeof ( user - > context ) - 1 ) ;
2003-03-31 07:13:36 +00:00
while ( v ) {
if ( ! strcasecmp ( v - > name , " context " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( user - > context , v - > value , sizeof ( user - > context ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " bridge " ) ) {
user - > bridge = ast_true ( v - > value ) ;
2003-09-22 06:21:03 +00:00
} else if ( ! strcasecmp ( v - > name , " nat " ) ) {
user - > nat = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " noFastStart " ) ) {
2004-12-15 23:24:13 +00:00
user - > options . noFastStart = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " noH245Tunneling " ) ) {
2004-12-15 23:24:13 +00:00
user - > options . noH245Tunneling = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " noSilenceSuppression " ) ) {
2004-12-15 23:24:13 +00:00
user - > options . noSilenceSuppression = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " secret " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( user - > secret , v - > value , sizeof ( user - > secret ) - 1 ) ;
2003-07-23 19:55:13 +00:00
} else if ( ! strcasecmp ( v - > name , " callerid " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( user - > callerid , v - > value , sizeof ( user - > callerid ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " accountcode " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( user - > accountcode , v - > value , sizeof ( user - > accountcode ) - 1 ) ;
2004-12-15 23:24:13 +00:00
} else if ( ! strcasecmp ( v - > name , " progress_setup " ) ) {
int progress_setup = atoi ( v - > value ) ;
if ( ( progress_setup ! = 0 ) & &
( progress_setup ! = 1 ) & &
( progress_setup ! = 3 ) & &
( progress_setup ! = 8 ) ) {
ast_log ( LOG_WARNING , " Invalid value %d for progress_setup at line %d, assuming 0 \n " , progress_setup , v - > lineno ) ;
progress_setup = 0 ;
}
user - > options . progress_setup = progress_setup ;
} else if ( ! strcasecmp ( v - > name , " progress_alert " ) ) {
int progress_alert = atoi ( v - > value ) ;
if ( ( progress_alert ! = 0 ) & &
( progress_alert ! = 8 ) ) {
ast_log ( LOG_WARNING , " Invalud value %d for progress_alert at line %d, assuming 0 \n " , progress_alert , v - > lineno ) ;
progress_alert = 0 ;
}
user - > options . progress_alert = progress_alert ;
} else if ( ! strcasecmp ( v - > name , " progress_audio " ) ) {
user - > options . progress_audio = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " dtmfcodec " ) ) {
user - > options . dtmfcodec = atoi ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " host " ) ) {
if ( ! strcasecmp ( v - > value , " dynamic " ) ) {
2004-09-30 19:36:46 +00:00
ast_log ( LOG_ERROR , " A dynamic host on a type=user does not make any sense \n " ) ;
2003-03-31 07:13:36 +00:00
free ( user ) ;
return NULL ;
} else if ( ast_get_ip ( & user - > addr , v - > value ) ) {
free ( user ) ;
return NULL ;
}
2003-03-31 20:26:08 +00:00
/* Let us know we need to use ip authentication */
user - > host = 1 ;
2003-03-31 07:13:36 +00:00
} 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 ;
}
}
v = v - > next ;
}
}
return user ;
}
static struct oh323_peer * build_peer ( char * name , struct ast_variable * v )
{
struct oh323_peer * peer ;
struct oh323_peer * prev ;
2004-10-04 10:13:01 +00:00
struct ast_ha * oldha = NULL ;
2003-03-31 07:13:36 +00:00
int found = 0 ;
2004-10-14 05:21:12 +00:00
int format ;
2003-03-31 07:13:36 +00:00
prev = NULL ;
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
peer = peerl . peers ;
while ( peer ) {
if ( ! strcasecmp ( peer - > name , name ) ) {
break ;
}
prev = peer ;
peer = peer - > next ;
}
if ( peer ) {
found + + ;
/* Already in the list, remove it and it will be added back (or FREE'd) */
if ( prev ) {
prev - > next = peer - > next ;
} else {
peerl . peers = peer - > next ;
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
} else {
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & peerl . lock ) ;
2004-06-26 03:50:14 +00:00
peer = ( struct oh323_peer * ) malloc ( sizeof ( struct oh323_peer ) ) ;
2005-02-13 07:45:40 +00:00
if ( peer )
memset ( peer , 0 , sizeof ( struct oh323_peer ) ) ;
2003-03-31 07:13:36 +00:00
}
if ( peer ) {
if ( ! found ) {
2004-10-04 10:13:01 +00:00
strncpy ( peer - > name , name , sizeof ( peer - > name ) - 1 ) ;
peer - > addr . sin_port = htons ( h323_signalling_port ) ;
2004-09-30 19:36:46 +00:00
peer - > addr . sin_family = AF_INET ;
2003-03-31 07:13:36 +00:00
}
2004-09-30 19:36:46 +00:00
oldha = peer - > ha ;
2004-10-04 10:13:01 +00:00
peer - > ha = NULL ;
2004-09-30 19:36:46 +00:00
peer - > addr . sin_family = AF_INET ;
peer - > capability = capability ;
2004-12-15 23:24:13 +00:00
peer - > options . dtmfcodec = 101 ;
peer - > dtmfmode = H323_DTMF_RFC2833 ;
2003-03-31 07:13:36 +00:00
while ( v ) {
2004-09-30 19:36:46 +00:00
if ( ! strcasecmp ( v - > name , " bridge " ) ) {
2003-03-31 07:13:36 +00:00
peer - > bridge = ast_true ( v - > value ) ;
2004-09-30 19:36:46 +00:00
} else if ( ! strcasecmp ( v - > name , " nat " ) ) {
peer - > nat = ast_true ( v - > value ) ;
2004-10-04 10:13:01 +00:00
} else if ( ! strcasecmp ( v - > name , " noFastStart " ) ) {
2004-12-15 23:24:13 +00:00
peer - > options . noFastStart = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " noH245Tunneling " ) ) {
2004-12-15 23:24:13 +00:00
peer - > options . noH245Tunneling = ast_true ( v - > value ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " noSilenceSuppression " ) ) {
2004-12-15 23:24:13 +00:00
peer - > options . noSilenceSuppression = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " progress_setup " ) ) {
int progress_setup = atoi ( v - > value ) ;
if ( ( progress_setup ! = 0 ) & &
( progress_setup ! = 1 ) & &
( progress_setup ! = 3 ) & &
( progress_setup ! = 8 ) ) {
ast_log ( LOG_WARNING , " Invalid value %d for progress_setup at line %d, assuming 0 \n " , progress_setup , v - > lineno ) ;
progress_setup = 0 ;
}
peer - > options . progress_setup = progress_setup ;
} else if ( ! strcasecmp ( v - > name , " progress_alert " ) ) {
int progress_alert = atoi ( v - > value ) ;
if ( ( progress_alert ! = 0 ) & &
( progress_alert ! = 8 ) ) {
ast_log ( LOG_WARNING , " Invalid value %d for progress_alert at line %d, assuming 0 \n " , progress_alert , v - > lineno ) ;
progress_alert = 0 ;
}
peer - > options . progress_alert = progress_alert ;
} else if ( ! strcasecmp ( v - > name , " progress_audio " ) ) {
peer - > options . progress_audio = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " dtmfcodec " ) ) {
peer - > options . dtmfcodec = atoi ( v - > value ) ;
2004-09-30 19:36:46 +00:00
} else if ( ! strcasecmp ( v - > name , " dtmfmode " ) ) {
2004-10-04 10:13:01 +00:00
if ( ! strcasecmp ( v - > value , " inband " ) ) {
2004-09-30 19:36:46 +00:00
peer - > dtmfmode = H323_DTMF_INBAND ;
2004-10-04 10:13:01 +00:00
} else if ( ! strcasecmp ( v - > value , " rfc2833 " ) ) {
2004-09-30 19:36:46 +00:00
peer - > dtmfmode = H323_DTMF_RFC2833 ;
} else {
ast_log ( LOG_WARNING , " Unknown DTMF Mode %s, using RFC2833 \n " , v - > value ) ;
peer - > dtmfmode = H323_DTMF_RFC2833 ;
}
2004-10-14 05:21:12 +00:00
} else if ( ! strcasecmp ( v - > name , " allow " ) ) {
format = ast_getformatbyname ( v - > value ) ;
if ( format < 1 ) {
ast_log ( LOG_WARNING , " Cannot allow unknown format '%s' \n " , v - > value ) ;
} else {
peer - > capability | = format ;
}
} else if ( ! strcasecmp ( v - > name , " disallow " ) ) {
format = ast_getformatbyname ( v - > value ) ;
if ( format < 1 ) {
ast_log ( LOG_WARNING , " Cannot disallow unknown format '%s' \n " , v - > value ) ;
} else {
peer - > capability | = ~ format ;
}
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " host " ) ) {
if ( ! strcasecmp ( v - > value , " dynamic " ) ) {
2004-09-30 19:36:46 +00:00
ast_log ( LOG_ERROR , " Dynamic host configuration not implemented. \n " ) ;
2003-03-31 07:13:36 +00:00
free ( peer ) ;
return NULL ;
}
if ( ast_get_ip ( & peer - > addr , v - > value ) ) {
2004-10-14 05:21:12 +00:00
ast_log ( LOG_ERROR , " Could not determine IP for %s \n " , v - > value ) ;
2003-03-31 07:13:36 +00:00
free ( peer ) ;
return NULL ;
}
2004-10-04 10:13:01 +00:00
} else if ( ! strcasecmp ( v - > name , " port " ) ) {
peer - > addr . sin_port = htons ( atoi ( v - > value ) ) ;
}
2003-03-31 07:13:36 +00:00
v = v - > next ;
}
}
return peer ;
}
/**
* Send ( play ) the specified digit to the channel .
*
*/
static int oh323_digit ( struct ast_channel * c , char digit )
{
2005-03-04 06:47:24 +00:00
struct oh323_pvt * p = ( struct oh323_pvt * ) c - > tech_pvt ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Sending digit %c on %s \n " , digit , c - > name ) ;
if ( ! p )
return - 1 ;
ast_mutex_lock ( & p - > lock ) ;
if ( p - > rtp & & ( p - > dtmfmode & H323_DTMF_RFC2833 ) ) {
2003-03-31 07:13:36 +00:00
ast_rtp_senddigit ( p - > rtp , digit ) ;
}
/* If in-band DTMF is desired, send that */
2005-04-04 15:54:34 +00:00
if ( ( p - > dtmfmode & H323_DTMF_INBAND ) ) {
2003-03-31 07:13:36 +00:00
h323_send_tone ( p - > cd . call_token , digit ) ;
2004-10-28 06:06:58 +00:00
}
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & p - > lock ) ;
oh323_update_info ( c ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
/**
* 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 )
2004-11-11 19:51:55 +00:00
{
int res = 0 ;
2005-03-04 06:47:24 +00:00
struct oh323_pvt * pvt = ( struct oh323_pvt * ) c - > tech_pvt ;
2004-11-11 19:51:55 +00:00
char addr [ INET_ADDRSTRLEN ] ;
2004-12-20 00:14:19 +00:00
char called_addr [ 1024 ] ;
2004-11-11 19:51:55 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug ) {
ast_log ( LOG_DEBUG , " Calling to %s on %s \n " , dest , c - > name ) ;
}
if ( ( c - > _state ! = AST_STATE_DOWN ) & & ( c - > _state ! = AST_STATE_RESERVED ) ) {
2004-11-11 19:51:55 +00:00
ast_log ( LOG_WARNING , " Line is already in use (%s) \n " , c - > name ) ;
return - 1 ;
}
if ( usingGk ) {
pvt - > options . port = h323_signalling_port ;
2005-04-04 15:54:34 +00:00
if ( ast_strlen_zero ( pvt - > exten ) ) {
strncpy ( called_addr , dest , sizeof ( called_addr ) ) ;
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s " , pvt - > exten , dest ) ;
}
2004-11-11 19:51:55 +00:00
} else {
ast_inet_ntoa ( addr , sizeof ( addr ) , pvt - > sa . sin_addr ) ;
pvt - > options . port = htons ( pvt - > sa . sin_port ) ;
2005-04-04 15:54:34 +00:00
if ( ast_strlen_zero ( pvt - > exten ) ) {
snprintf ( called_addr , sizeof ( called_addr ) , " %s:%d " , addr , pvt - > options . port ) ;
} else {
snprintf ( called_addr , sizeof ( called_addr ) , " %s@%s:%d " , pvt - > exten , addr , pvt - > options . port ) ;
}
2004-12-16 02:03:19 +00:00
}
2005-04-04 15:54:34 +00:00
/* make sure null terminated */
called_addr [ sizeof ( called_addr ) - 1 ] = ' \0 ' ;
2004-12-16 02:03:19 +00:00
if ( c - > cid . cid_num ) {
strncpy ( pvt - > options . cid_num , c - > cid . cid_num , sizeof ( pvt - > options . cid_num ) ) ;
}
if ( c - > cid . cid_name ) {
strncpy ( pvt - > options . cid_name , c - > cid . cid_name , sizeof ( pvt - > options . cid_name ) ) ;
}
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
2004-12-15 23:24:13 +00:00
ast_log ( LOG_DEBUG , " Placing outgoing call to %s, %d \n " , called_addr , pvt - > options . dtmfcodec ) ;
res = h323_make_call ( called_addr , & ( pvt - > cd ) , & pvt - > options ) ;
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 )
ast_log ( LOG_DEBUG , " Answering on %s \n " , c - > name ) ;
ast_mutex_lock ( & pvt - > lock ) ;
token = pvt - > cd . call_token ? strdup ( pvt - > cd . call_token ) : NULL ;
ast_mutex_unlock ( & pvt - > lock ) ;
res = h323_answering_call ( token , 0 ) ;
if ( token )
free ( token ) ;
oh323_update_info ( c ) ;
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 ;
2003-03-31 07:13:36 +00:00
int needcancel = 0 ;
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 )
ast_log ( LOG_DEBUG , " Hanging up 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 ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_DEBUG , " Asked to hangup channel not connected \n " ) ;
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 ;
}
2004-10-28 06:06:58 +00:00
if ( ! c | | ( c - > _state ! = AST_STATE_UP ) ) {
2003-03-31 07:13:36 +00:00
needcancel = 1 ;
2004-10-28 06:06:58 +00:00
}
2003-03-31 07:13:36 +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 {
char * cause = pbx_builtin_getvar_helper ( c , " DIALSTATUS " ) ;
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 ) {
call_token = pvt - > cd . call_token ? strdup ( pvt - > cd . call_token ) : NULL ;
if ( call_token ) {
/* Release lock to eliminate deadlock */
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323_clear_call ( call_token , q931cause ) ) {
ast_log ( LOG_DEBUG , " ClearCall failed. \n " ) ;
}
free ( call_token ) ;
ast_mutex_lock ( & pvt - > lock ) ;
2004-01-06 16:51:34 +00:00
}
2004-05-18 10:33:46 +00:00
}
2005-04-04 15:54:34 +00:00
pvt - > needdestroy = 1 ;
2003-03-31 07:13:36 +00:00
2003-04-23 21:52:46 +00:00
/* Update usage counter */
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & usecnt_lock ) ;
2003-04-23 21:52:46 +00:00
usecnt - - ;
2004-10-22 19:04:02 +00:00
if ( usecnt < 0 ) {
2003-04-23 21:52:46 +00:00
ast_log ( LOG_WARNING , " Usecnt < 0 \n " ) ;
2004-10-22 19:04:02 +00:00
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & usecnt_lock ) ;
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2005-04-04 15:54:34 +00:00
ast_update_use_count ( ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
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
{
2004-10-04 10:13:01 +00:00
/* Retrieve audio/etc from channel. Assumes pvt->lock is already held. */
2003-03-31 07:13:36 +00:00
struct ast_frame * f ;
static struct ast_frame null_frame = { AST_FRAME_NULL , } ;
2003-09-22 06:21:03 +00:00
2004-10-28 06:06:58 +00:00
/* Only apply it for the first packet, we just need the correct ip/port */
if ( pvt - > nat ) {
ast_rtp_setnat ( pvt - > rtp , pvt - > nat ) ;
pvt - > 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 */
2004-10-28 06:06:58 +00:00
if ( f & & ( f - > frametype = = AST_FRAME_DTMF ) & & ! ( pvt - > dtmfmode & H323_DTMF_RFC2833 ) ) {
2003-03-31 07:13:36 +00:00
return & 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 */
if ( ast_mutex_trylock ( & pvt - > owner - > lock ) ) {
ast_log ( LOG_NOTICE , " Format changed but channel is locked. Ignoring frame... \n " ) ;
return & null_frame ;
}
2003-03-31 07:13:36 +00:00
ast_log ( LOG_DEBUG , " 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 ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
2004-10-28 06:06:58 +00:00
}
2003-03-31 07:13:36 +00:00
/* Do in-band DTMF detection */
2005-02-13 07:45:40 +00:00
if ( ( pvt - > dtmfmode & H323_DTMF_INBAND ) & & pvt - > vad ) {
2004-10-04 10:13:01 +00:00
f = ast_dsp_process ( pvt - > owner , pvt - > vad , f ) ;
2005-02-13 07:45:40 +00:00
if ( f & & ( f - > frametype = = AST_FRAME_DTMF ) ) {
2004-10-28 06:06:58 +00:00
ast_log ( LOG_DEBUG , " Received in-band digit %c. \n " , f - > subclass ) ;
2004-10-04 10:13:01 +00:00
}
}
2003-03-31 07:13:36 +00:00
}
}
return f ;
}
static struct ast_frame * oh323_read ( struct ast_channel * c )
{
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-04-04 15:54:34 +00:00
oh323_update_info ( c ) ;
2004-10-04 10:13:01 +00:00
fr = oh323_rtp_read ( pvt ) ;
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 ) ;
if ( pvt - > rtp ) {
res = ast_rtp_write ( pvt - > rtp , frame ) ;
2003-03-31 07:13:36 +00:00
}
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
}
return res ;
}
static int oh323_indicate ( struct ast_channel * c , int condition )
{
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 ;
2004-12-15 23:24:13 +00:00
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
token = ( pvt - > cd . call_token ? strdup ( pvt - > cd . call_token ) : NULL ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323debug )
ast_log ( LOG_DEBUG , " OH323: Indicating %d on %s \n " , condition , token ) ;
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 ) ;
2004-05-20 07:07:18 +00:00
break ;
2004-12-15 23:24:13 +00:00
}
2005-04-04 15:54:34 +00:00
if ( token )
free ( token ) ;
2004-05-20 07:07:18 +00:00
return - 1 ;
case AST_CONTROL_PROGRESS :
if ( c - > _state ! = AST_STATE_UP ) {
2005-04-04 15:54:34 +00:00
h323_send_progress ( token ) ;
2004-05-20 07:07:18 +00:00
break ;
2003-03-31 07:13:36 +00:00
}
2005-04-04 15:54:34 +00:00
if ( token )
free ( token ) ;
2004-05-20 07:07:18 +00:00
return - 1 ;
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 ) ;
2004-10-04 10:13:01 +00:00
pvt - > alreadygone = 1 ;
2004-05-20 07:07:18 +00:00
ast_softhangup_nolock ( c , AST_SOFTHANGUP_DEV ) ;
2003-03-31 07:13:36 +00:00
break ;
}
2005-04-04 15:54:34 +00:00
if ( token )
free ( token ) ;
2004-05-20 07:07:18 +00:00
return - 1 ;
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-10-04 10:13:01 +00:00
pvt - > alreadygone = 1 ;
2004-05-20 07:07:18 +00:00
ast_softhangup_nolock ( c , AST_SOFTHANGUP_DEV ) ;
2003-03-31 07:13:36 +00:00
break ;
}
2005-04-04 15:54:34 +00:00
if ( token )
free ( token ) ;
2004-05-20 07:07:18 +00:00
return - 1 ;
2004-06-14 21:18:52 +00:00
case AST_CONTROL_PROCEEDING :
2003-03-31 07:13:36 +00:00
case - 1 :
2005-04-04 15:54:34 +00:00
if ( token )
free ( token ) ;
2003-12-24 22:38:24 +00:00
return - 1 ;
2003-03-31 07:13:36 +00:00
default :
2005-04-04 15:54:34 +00:00
ast_log ( LOG_WARNING , " Don't know how to indicate condition %d on %s \n " , condition , token ) ;
if ( token )
free ( token ) ;
2003-03-31 07:13:36 +00:00
return - 1 ;
}
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " OH323: Indicated %d on %s \n " , condition , token ) ;
if ( token )
free ( token ) ;
oh323_update_info ( c ) ;
2004-12-15 23:24:13 +00:00
return - 1 ;
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 ;
}
2004-10-04 10:13:01 +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 ;
2003-03-31 07:13:36 +00:00
int fmt ;
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 ) ;
ch = ast_channel_alloc ( 1 ) ;
2004-12-15 23:24:13 +00:00
/* Update usage counter */
ast_mutex_lock ( & usecnt_lock ) ;
usecnt + + ;
ast_mutex_unlock ( & usecnt_lock ) ;
ast_update_use_count ( ) ;
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 ;
2004-07-16 04:40:54 +00:00
snprintf ( ch - > name , sizeof ( ch - > name ) , " H323/%s " , host ) ;
2004-10-04 10:13:01 +00:00
ch - > nativeformats = pvt - > capability ;
2004-10-22 19:04:02 +00:00
if ( ! ch - > nativeformats ) {
2003-08-16 17:00:22 +00:00
ch - > nativeformats = capability ;
2004-10-22 19:04:02 +00:00
}
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 - > type = type ;
2004-10-04 10:13:01 +00:00
ch - > fds [ 0 ] = ast_rtp_fd ( pvt - > rtp ) ;
2004-10-22 19:04:02 +00:00
if ( state = = AST_STATE_RING ) {
2003-08-16 17:00:22 +00:00
ch - > rings = 1 ;
2004-10-22 19:04:02 +00:00
}
2003-08-16 17:00:22 +00:00
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 ;
2003-03-31 07:13:36 +00:00
/* Allocate dsp for in-band DTMF support */
2004-10-04 10:13:01 +00:00
if ( pvt - > dtmfmode & H323_DTMF_INBAND ) {
pvt - > vad = ast_dsp_new ( ) ;
ast_dsp_set_features ( pvt - > vad , DSP_FEATURE_DTMF_DETECT ) ;
2003-08-16 17:00: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 ;
2003-03-31 07:13:36 +00:00
/* Set the owner of this channel */
2004-10-04 10:13:01 +00:00
pvt - > owner = ch ;
2003-03-31 07:13:36 +00:00
2004-10-04 10:13:01 +00:00
strncpy ( ch - > context , pvt - > context , sizeof ( ch - > context ) - 1 ) ;
strncpy ( ch - > exten , pvt - > exten , sizeof ( ch - > exten ) - 1 ) ;
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 ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( ch - > accountcode , pvt - > accountcode , sizeof ( ch - > accountcode ) - 1 ) ;
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
}
if ( ! ast_strlen_zero ( pvt - > cid_num ) ) {
ch - > cid . cid_num = strdup ( pvt - > cid_num ) ;
2004-12-18 07:10:46 +00:00
} else if ( pvt - > cd . call_source_e164 & & ! ast_strlen_zero ( pvt - > cd . call_source_e164 ) ) {
2004-12-18 04:09:39 +00:00
ch - > cid . cid_num = strdup ( pvt - > cd . call_source_e164 ) ;
2004-10-22 19:04:02 +00:00
}
if ( ! ast_strlen_zero ( pvt - > cid_name ) ) {
ch - > cid . cid_name = strdup ( pvt - > cid_name ) ;
2004-12-18 07:10:46 +00:00
} else if ( pvt - > cd . call_source_e164 & & ! ast_strlen_zero ( pvt - > cd . call_source_name ) ) {
2004-12-18 04:09:39 +00:00
ch - > cid . cid_name = strdup ( pvt - > cd . call_source_name ) ;
2004-10-22 19:04:02 +00:00
}
if ( ! ast_strlen_zero ( pvt - > rdnis ) ) {
ch - > cid . cid_rdnis = strdup ( pvt - > rdnis ) ;
}
if ( ! ast_strlen_zero ( pvt - > exten ) & & strcmp ( pvt - > exten , " s " ) ) {
ch - > cid . cid_dnid = strdup ( pvt - > exten ) ;
}
2004-04-28 14:35:20 +00:00
ast_setstate ( ch , state ) ;
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 ) ;
ch = NULL ;
2003-03-31 07:13:36 +00:00
}
}
2004-10-22 19:04:02 +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
2004-10-04 10:13:01 +00:00
pvt = ( struct oh323_pvt * ) malloc ( sizeof ( struct oh323_pvt ) ) ;
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 ;
}
2004-10-04 10:13:01 +00:00
memset ( pvt , 0 , sizeof ( struct oh323_pvt ) ) ;
pvt - > rtp = ast_rtp_new ( sched , io , 1 , 0 ) ;
if ( ! pvt - > rtp ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Unable to create RTP session: %s \n " , strerror ( errno ) ) ;
2004-10-04 10:13:01 +00:00
free ( pvt ) ;
2003-03-31 07:13:36 +00:00
return NULL ;
}
2004-10-04 10:13:01 +00:00
ast_rtp_settos ( pvt - > rtp , tos ) ;
ast_mutex_init ( & pvt - > lock ) ;
2004-10-01 04:50:34 +00:00
/* Ensure the call token is allocated */
2004-10-04 10:13:01 +00:00
if ( ( pvt - > cd ) . call_token = = NULL ) {
( pvt - > cd ) . call_token = ( char * ) malloc ( 128 ) ;
2004-10-01 04:50:34 +00:00
}
2004-10-04 10:13:01 +00:00
if ( ! pvt - > cd . call_token ) {
2004-10-01 04:50:34 +00:00
ast_log ( LOG_ERROR , " Not enough memory to alocate call token \n " ) ;
return NULL ;
}
2005-02-13 07:45:40 +00:00
memset ( ( char * ) ( pvt - > cd ) . call_token , 0 , 128 ) ;
2004-10-04 10:13:01 +00:00
pvt - > cd . call_reference = callid ;
pvt - > bridge = bridging ;
pvt - > dtmfmode = dtmfmode ;
if ( pvt - > dtmfmode & H323_DTMF_RFC2833 ) {
pvt - > nonCodecCapability | = AST_RTP_DTMF ;
2004-10-01 04:50:34 +00:00
}
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > context , default_context , sizeof ( pvt - > context ) - 1 ) ;
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
}
2004-09-19 16:53:01 +00:00
static struct oh323_pvt * find_call ( int call_reference , const char * token )
2003-03-31 07:13:36 +00:00
{
2004-10-04 10:13:01 +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 ) ;
2004-10-04 10:13:01 +00:00
pvt = iflist ;
while ( pvt ) {
2005-04-04 15:54:34 +00:00
if ( ! pvt - > needdestroy & & ( ( signed int ) pvt - > cd . call_reference = = call_reference ) ) {
2004-10-01 04:50:34 +00:00
/* Found the call */
2004-10-28 06:06:58 +00:00
if ( ( token ! = NULL ) & & ( ! strcmp ( pvt - > cd . call_token , token ) ) ) {
2004-09-19 16:53:01 +00:00
ast_mutex_unlock ( & iflock ) ;
2004-10-04 10:13:01 +00:00
return pvt ;
2004-10-22 19:04:02 +00:00
} else if ( token = = NULL ) {
ast_log ( LOG_DEBUG , " Call Token is NULL \n " ) ;
2004-09-19 16:53:01 +00:00
ast_mutex_unlock ( & iflock ) ;
2004-10-04 10:13:01 +00:00
return pvt ;
2004-09-19 16:53:01 +00:00
}
2004-03-20 14:25:39 +00:00
}
2004-10-04 10:13:01 +00:00
pvt = pvt - > next ;
2004-03-20 14:25:39 +00:00
}
ast_mutex_unlock ( & iflock ) ;
2004-09-19 16:53:01 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2004-10-04 10:13:01 +00:00
struct oh323_user * find_user ( const call_details_t cd )
{
struct oh323_user * u ;
char iabuf [ INET_ADDRSTRLEN ] ;
u = userl . users ;
2004-10-22 19:04:02 +00:00
if ( userbyalias ) {
2004-10-04 10:13:01 +00:00
while ( u ) {
if ( ! strcasecmp ( u - > name , cd . call_source_aliases ) ) {
break ;
}
u = u - > next ;
}
} else {
while ( u ) {
if ( ! strcasecmp ( cd . sourceIp , ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , u - > addr . sin_addr ) ) ) {
break ;
}
u = u - > next ;
}
}
return u ;
}
2004-12-20 00:14:19 +00:00
struct oh323_peer * find_peer ( const char * peer , struct sockaddr_in * sin )
2004-10-04 10:13:01 +00:00
{
struct oh323_peer * p = NULL ;
2004-10-14 05:21:12 +00:00
static char iabuf [ INET_ADDRSTRLEN ] ;
2004-10-04 10:13:01 +00:00
p = peerl . peers ;
if ( peer ) {
while ( p ) {
if ( ! strcasecmp ( p - > name , peer ) ) {
2004-10-14 05:21:12 +00:00
ast_log ( LOG_DEBUG , " Found peer %s by name \n " , peer ) ;
2004-10-04 10:13:01 +00:00
break ;
}
p = p - > next ;
}
} else {
/* find by sin */
2004-10-14 23:59:22 +00:00
if ( sin ) {
while ( p ) {
if ( ( ! inaddrcmp ( & p - > addr , sin ) ) | |
( p - > addr . sin_addr . s_addr = = sin - > sin_addr . s_addr ) ) {
ast_log ( LOG_DEBUG , " Found peer %s/%s by addr \n " , peer , ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , p - > addr . sin_addr ) ) ;
break ;
}
p = p - > next ;
2004-10-04 10:13:01 +00:00
}
2004-10-14 23:59:22 +00:00
}
2004-10-04 10:13:01 +00:00
}
2004-10-14 05:21:12 +00:00
if ( ! p ) {
2004-10-14 23:59:22 +00:00
ast_log ( LOG_DEBUG , " Could not find peer %s by name or address \n " , peer ) ;
2004-10-14 05:21:12 +00:00
}
2004-10-04 10:13:01 +00:00
return p ;
}
static int create_addr ( struct oh323_pvt * pvt , char * opeer )
2003-03-31 07:13:36 +00:00
{
2004-09-30 19:36:46 +00:00
struct hostent * hp ;
struct ast_hostent ahp ;
struct oh323_peer * p ;
2004-10-01 04:50:34 +00:00
int portno ;
2004-09-30 19:36:46 +00:00
int found = 0 ;
char * port ;
2004-10-04 10:13:01 +00:00
char * hostn ;
2004-09-30 19:36:46 +00:00
char peer [ 256 ] = " " ;
strncpy ( peer , opeer , sizeof ( peer ) - 1 ) ;
port = strchr ( peer , ' : ' ) ;
if ( port ) {
* port = ' \0 ' ;
port + + ;
}
2004-10-04 10:13:01 +00:00
pvt - > sa . sin_family = AF_INET ;
2004-09-30 19:36:46 +00:00
ast_mutex_lock ( & peerl . lock ) ;
p = find_peer ( peer , NULL ) ;
if ( p ) {
found + + ;
2004-10-04 10:13:01 +00:00
pvt - > capability = p - > capability ;
pvt - > nat = p - > nat ;
if ( pvt - > rtp ) {
ast_log ( LOG_DEBUG , " Setting NAT on RTP to %d \n " , pvt - > nat ) ;
ast_rtp_setnat ( pvt - > rtp , pvt - > nat ) ;
2004-09-30 19:36:46 +00:00
}
2004-12-15 23:24:13 +00:00
memcpy ( & pvt - > options , & p - > options , sizeof ( pvt - > options ) ) ;
if ( p - > dtmfmode ) {
2004-10-04 10:13:01 +00:00
pvt - > dtmfmode = p - > dtmfmode ;
if ( pvt - > dtmfmode & H323_DTMF_RFC2833 ) {
pvt - > nonCodecCapability | = AST_RTP_DTMF ;
2004-09-30 19:36:46 +00:00
} else {
2004-10-04 10:13:01 +00:00
pvt - > nonCodecCapability & = ~ AST_RTP_DTMF ;
2004-09-30 19:36:46 +00:00
}
}
2004-10-01 04:50:34 +00:00
if ( p - > addr . sin_addr . s_addr ) {
2004-10-04 10:13:01 +00:00
pvt - > sa . sin_addr = p - > addr . sin_addr ;
pvt - > sa . sin_port = p - > addr . sin_port ;
2004-10-14 05:21:12 +00:00
}
2004-10-01 04:50:34 +00:00
}
ast_mutex_unlock ( & peerl . lock ) ;
if ( ! p & & ! found ) {
hostn = peer ;
if ( port ) {
portno = atoi ( port ) ;
} else {
2004-10-04 10:13:01 +00:00
portno = h323_signalling_port ;
2004-10-01 04:50:34 +00:00
}
hp = ast_gethostbyname ( hostn , & ahp ) ;
if ( hp ) {
2004-12-15 23:24:13 +00:00
memcpy ( & pvt - > options , & global_options , sizeof ( pvt - > options ) ) ;
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 ) ;
2004-10-01 04:50:34 +00:00
return 0 ;
} else {
ast_log ( LOG_WARNING , " No such host: %s \n " , peer ) ;
return - 1 ;
}
} else if ( ! p ) {
return - 1 ;
2004-10-04 10:13:01 +00:00
} else {
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 ;
2003-03-31 07:13:36 +00:00
char tmp [ 256 ] ;
2003-06-03 07:11:52 +00:00
2003-03-31 07:13:36 +00:00
ast_log ( LOG_DEBUG , " type=%s, format=%d, data=%s. \n " , type , format , ( char * ) data ) ;
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 ;
}
2003-03-31 07:13:36 +00:00
oldformat = format ;
2004-10-01 04:50:34 +00:00
format & = ( ( AST_FORMAT_MAX_AUDIO < < 1 ) - 1 ) ;
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 ) ;
return NULL ;
}
2004-10-14 05:21:12 +00:00
/* Assign default capabilities */
2004-10-04 10:13:01 +00:00
pvt - > capability = capability ;
2004-10-14 05:21:12 +00:00
pvt - > dtmfmode = H323_DTMF_RFC2833 ;
2004-09-30 19:36:46 +00:00
strncpy ( tmp , dest , sizeof ( tmp ) - 1 ) ;
2003-03-31 07:13:36 +00:00
host = strchr ( tmp , ' @ ' ) ;
if ( host ) {
* host = ' \0 ' ;
host + + ;
ext = tmp ;
} else {
host = tmp ;
ext = NULL ;
}
2004-09-30 19:36:46 +00:00
strtok_r ( host , " / " , & ( h323id ) ) ;
2004-07-09 08:52:35 +00:00
if ( h323id & & ! 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 ) {
2004-11-11 21:30:30 +00:00
strncpy ( pvt - > exten , ext , sizeof ( pvt - > exten ) - 1 ) ;
2004-01-11 17:51:35 +00:00
}
2004-11-11 21:30:30 +00:00
ast_log ( LOG_DEBUG , " Extension: %s Host: %s \n " , pvt - > exten , host ) ;
2004-10-04 10:13:01 +00:00
if ( ! usingGk ) {
if ( create_addr ( pvt , host ) ) {
oh323_destroy ( pvt ) ;
return NULL ;
}
2004-09-30 19:36:46 +00:00
}
2004-12-15 23:24:13 +00:00
2004-10-14 05:21:12 +00:00
/* pass on our capabilites to the H.323 stack */
ast_mutex_lock ( & caplock ) ;
h323_set_capability ( pvt - > capability , pvt - > dtmfmode ) ;
ast_mutex_unlock ( & caplock ) ;
2004-10-04 10:13:01 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
tmpc = oh323_new ( pvt , AST_STATE_DOWN , host ) ;
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 ) ;
2004-09-30 19:36:46 +00:00
}
ast_update_use_count ( ) ;
2003-03-31 07:13:36 +00:00
restart_monitor ( ) ;
return tmpc ;
}
2004-10-22 19:04:02 +00:00
/** Find a call by alias */
2003-12-24 22:38:24 +00:00
struct oh323_alias * find_alias ( const char * source_aliases )
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
a = aliasl . aliases ;
while ( a ) {
2003-12-24 22:38:24 +00:00
if ( ! strcasecmp ( a - > name , source_aliases ) ) {
2003-03-31 07:13:36 +00:00
break ;
}
a = a - > next ;
}
2003-12-24 22:38:24 +00:00
return a ;
2003-03-31 07:13:36 +00:00
}
/**
* Callback for sending digits from H .323 up to asterisk
*
*/
2004-09-19 16:53:01 +00:00
int send_digit ( unsigned call_reference , char digit , const char * token )
2003-03-31 07:13:36 +00:00
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt ;
2003-03-31 07:13:36 +00:00
struct ast_frame f ;
ast_log ( LOG_DEBUG , " Recieved Digit: %c \n " , digit ) ;
2004-10-04 10:13:01 +00:00
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Private structure not found in send_digit. \n " ) ;
return - 1 ;
}
memset ( & f , 0 , sizeof ( f ) ) ;
f . frametype = AST_FRAME_DTMF ;
2004-10-04 10:13:01 +00:00
f . subclass = digit ;
f . datalen = 0 ;
f . samples = 800 ;
f . offset = 0 ;
f . data = NULL ;
f . mallocd = 0 ;
f . src = " SEND_DIGIT " ;
return ast_queue_frame ( pvt - > owner , & f ) ;
2003-03-31 07:13:36 +00:00
}
/**
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
*
2003-08-25 09:54:36 +00:00
* Returns the local RTP information
2003-03-31 07:13:36 +00:00
*/
2004-10-10 12:20:18 +00:00
struct rtp_info * external_rtp_create ( unsigned call_reference , const char * token )
2003-03-31 07:13:36 +00:00
{
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 ;
2004-10-10 12:20:18 +00:00
static char iabuf [ INET_ADDRSTRLEN ] ;
2003-03-31 07:13:36 +00:00
2004-10-10 12:20:18 +00:00
info = ( struct rtp_info * ) malloc ( sizeof ( struct rtp_info ) ) ;
if ( ! info ) {
ast_log ( LOG_ERROR , " Unable to allocated info structure, this is very bad \n " ) ;
return NULL ;
}
2004-10-04 10:13:01 +00:00
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
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
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
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 ) ;
2004-10-28 06:06:58 +00:00
/* evil hack, until I (or someone?) figures out a better way */
2004-10-14 05:21:12 +00:00
info - > addr = ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , bindaddr . sin_addr ) ;
2003-08-25 09:54:36 +00:00
info - > port = ntohs ( us . sin_port ) ;
2004-10-14 05:29:55 +00:00
ast_log ( LOG_DEBUG , " 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
}
2004-12-15 23:24:13 +00:00
int progress ( unsigned call_reference , const char * token , int inband ) ;
2004-12-21 00:07:56 +00:00
/**
* Definition taken from rtp . c for rtpPayloadType because we need it here .
*/
struct rtpPayloadType {
int isAstFormat ; /* whether the following code is an AST_FORMAT */
int code ;
} ;
2004-10-10 12:20:18 +00:00
/**
* Call - back function passing remote ip / port information from H .323 to asterisk
*
* Returns nothing
*/
2004-12-21 00:07:56 +00:00
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
{
struct oh323_pvt * pvt = NULL ;
struct sockaddr_in them ;
2004-12-21 00:07:56 +00:00
struct rtpPayloadType rtptype ;
2004-10-10 12:20:18 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Setting up RTP connection for %s \n " , token ) ;
2004-10-10 12:20:18 +00:00
/* Find the call or allocate a private structure if call not found */
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: rtp \n " ) ;
return ;
}
2004-12-21 00:07:56 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2005-04-04 15:54:34 +00:00
if ( pvt - > alreadygone ) {
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
rtptype = ast_rtp_lookup_pt ( pvt - > rtp , pt ) ;
pvt - > nativeformats = rtptype . code ;
if ( pvt - > owner & & ! ast_mutex_trylock ( & pvt - > owner - > lock ) ) {
pvt - > owner - > nativeformats = pvt - > nativeformats ;
ast_set_read_format ( pvt - > owner , pvt - > owner - > readformat ) ;
ast_set_write_format ( pvt - > owner , pvt - > owner - > writeformat ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
2004-12-21 00:07:56 +00:00
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 */
them . sin_addr . s_addr = inet_addr ( remoteIp ) ;
2004-10-10 12:20:18 +00:00
them . sin_port = htons ( remotePort ) ;
ast_rtp_set_peer ( pvt - > rtp , & them ) ;
2004-12-15 23:24:13 +00:00
if ( pvt - > options . progress_audio ) {
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-12-15 23:24:13 +00:00
progress ( call_reference , token , 1 ) ;
2005-04-04 15:54:34 +00:00
} else
ast_mutex_unlock ( & pvt - > lock ) ;
if ( h323debug )
ast_log ( LOG_DEBUG , " RTP connection prepared for %s \n " , token ) ;
2004-12-21 00:07:56 +00:00
2004-10-10 12:20:18 +00:00
return ;
}
/**
* Call - back function to signal asterisk that the channel has been answered
* Returns nothing
*/
void connection_made ( unsigned call_reference , const char * token )
{
struct ast_channel * c = NULL ;
struct oh323_pvt * pvt = NULL ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Call %s answered \n " , token ) ;
2004-10-10 12:20:18 +00:00
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
ast_log ( LOG_ERROR , " Something is wrong: connection \n " ) ;
return ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
/* Inform asterisk about remote party connected only on outgoing calls */
if ( ! pvt - > outgoing ) {
ast_mutex_unlock ( & pvt - > lock ) ;
return ;
}
2004-10-10 12:20:18 +00:00
if ( ! pvt - > owner ) {
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-10-10 12:20:18 +00:00
ast_log ( LOG_ERROR , " Channel has no owner \n " ) ;
return ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > owner - > lock ) ;
2004-10-10 12:20:18 +00:00
c = pvt - > owner ;
ast_setstate ( c , AST_STATE_UP ) ;
ast_queue_control ( c , AST_CONTROL_ANSWER ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
2004-10-10 12:20:18 +00:00
return ;
}
2004-12-15 23:24:13 +00:00
int progress ( unsigned call_reference , const char * token , int inband )
{
struct oh323_pvt * p ;
ast_log ( LOG_DEBUG , " Received ALERT/PROGRESS message for %s tones \n " , ( inband ? " inband " : " self-generated " ) ) ;
p = find_call ( call_reference , token ) ;
if ( ! p ) {
ast_log ( LOG_ERROR , " Private structure not found in progress. \n " ) ;
return - 1 ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & p - > lock ) ;
2004-12-15 23:24:13 +00:00
if ( ! p - > owner ) {
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & p - > lock ) ;
2004-12-15 23:24:13 +00:00
ast_log ( LOG_ERROR , " No Asterisk channel associated with private structure. \n " ) ;
return - 1 ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & p - > owner - > lock ) ;
2004-12-15 23:24:13 +00:00
ast_queue_control ( p - > owner , ( inband ? AST_CONTROL_PROGRESS : AST_CONTROL_RINGING ) ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & p - > owner - > lock ) ;
ast_mutex_unlock ( & p - > lock ) ;
2004-12-15 23:24:13 +00:00
return 0 ;
}
2003-03-31 07:13:36 +00:00
/**
* Call - back function for incoming calls
*
* Returns 1 on success
*/
2004-12-15 23:24:13 +00:00
call_options_t * setup_incoming_call ( call_details_t cd )
2003-03-31 07:13:36 +00:00
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt = NULL ;
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
call_options_t * call_options ;
2004-06-30 16:56:51 +00:00
char iabuf [ INET_ADDRSTRLEN ] ;
2003-03-31 07:13:36 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Setting up incoming call for %s \n " , cd . call_token ) ;
2003-03-31 07:13:36 +00:00
/* allocate the call*/
2004-10-04 10:13:01 +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 " ) ;
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 */
2004-10-04 10:13:01 +00:00
pvt - > cd . call_token = strdup ( cd . call_token ) ;
pvt - > cd . call_source_aliases = strdup ( cd . call_source_aliases ) ;
pvt - > cd . call_dest_alias = strdup ( cd . call_dest_alias ) ;
pvt - > cd . call_source_name = strdup ( cd . call_source_name ) ;
pvt - > cd . call_source_e164 = strdup ( cd . call_source_e164 ) ;
pvt - > cd . call_dest_e164 = strdup ( cd . call_dest_e164 ) ;
2005-04-04 15:54:34 +00:00
call_options = & pvt - > options ;
2003-03-31 07:13:36 +00:00
if ( h323debug ) {
2003-12-24 22:38:24 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " Setting up Call \n " ) ;
2004-10-22 19:04:02 +00:00
ast_verbose ( VERBOSE_PREFIX_3 " \t Call token: [%s] \n " , pvt - > cd . call_token ) ;
ast_verbose ( VERBOSE_PREFIX_3 " \t Calling party name: [%s] \n " , pvt - > cd . call_source_name ) ;
ast_verbose ( VERBOSE_PREFIX_3 " \t Calling party number: [%s] \n " , pvt - > cd . call_source_e164 ) ;
ast_verbose ( VERBOSE_PREFIX_3 " \t Called party name: [%s] \n " , pvt - > cd . call_dest_alias ) ;
ast_verbose ( VERBOSE_PREFIX_3 " \t Called party number: [%s] \n " , pvt - > cd . call_dest_e164 ) ;
2003-03-31 07:13:36 +00:00
}
/* Decide if we are allowing Gatekeeper routed calls*/
2004-10-22 19:04:02 +00:00
if ( ( ! strcasecmp ( cd . sourceIp , gatekeeper ) ) & & ( gkroute = = - 1 ) & & ( usingGk ) ) {
2004-05-03 22:19:03 +00:00
if ( ! ast_strlen_zero ( cd . call_dest_e164 ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > exten , cd . call_dest_e164 , sizeof ( pvt - > exten ) - 1 ) ;
strncpy ( pvt - > context , default_context , sizeof ( pvt - > context ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else {
2003-12-24 22:38:24 +00:00
alias = find_alias ( cd . call_dest_alias ) ;
2003-03-31 07:13:36 +00:00
if ( ! alias ) {
ast_log ( LOG_ERROR , " Call for %s rejected, alias not found \n " , cd . call_dest_alias ) ;
2004-12-15 23:24:13 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > exten , alias - > name , sizeof ( pvt - > exten ) - 1 ) ;
strncpy ( pvt - > context , alias - > context , sizeof ( pvt - > context ) - 1 ) ;
2003-03-31 07:13:36 +00:00
}
} else {
/* Either this call is not from the Gatekeeper
or we are not allowing gk routed calls */
2003-12-09 05:14:23 +00:00
user = find_user ( cd ) ;
2003-03-31 07:13:36 +00:00
if ( ! user ) {
2004-10-04 10:13:01 +00:00
if ( ! ast_strlen_zero ( pvt - > cd . call_dest_e164 ) ) {
strncpy ( pvt - > exten , cd . call_dest_e164 , sizeof ( pvt - > exten ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else {
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > exten , cd . call_dest_alias , sizeof ( pvt - > exten ) - 1 ) ;
2003-03-31 07:13:36 +00:00
}
2004-05-03 22:19:03 +00:00
if ( ast_strlen_zero ( default_context ) ) {
2004-10-04 10:13:01 +00:00
ast_log ( LOG_ERROR , " Call from '%s' rejected due to no default context \n " , pvt - > cd . call_source_aliases ) ;
2004-12-15 23:24:13 +00:00
return NULL ;
2003-03-31 07:13:36 +00:00
}
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > context , default_context , sizeof ( pvt - > context ) - 1 ) ;
ast_log ( LOG_DEBUG , " Sending %s to context [%s] \n " , cd . call_source_aliases , pvt - > context ) ;
2004-12-15 23:24:13 +00:00
memset ( & pvt - > options , 0 , sizeof ( pvt - > options ) ) ;
2003-12-24 22:38:24 +00:00
} else {
2003-03-31 20:26:08 +00:00
if ( user - > host ) {
2004-06-29 12:56:46 +00:00
if ( strcasecmp ( cd . sourceIp , ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , user - > addr . sin_addr ) ) ) {
2004-05-20 21:56:12 +00:00
if ( ast_strlen_zero ( user - > context ) ) {
if ( ast_strlen_zero ( default_context ) ) {
ast_log ( LOG_ERROR , " Call from '%s' rejected due to non-matching IP address (%s) and no default context \n " , user - > name , cd . sourceIp ) ;
2004-12-15 23:24:13 +00:00
return NULL ;
2004-05-20 21:56:12 +00:00
}
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > context , default_context , sizeof ( pvt - > context ) - 1 ) ;
2004-05-20 21:56:12 +00:00
} else {
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > context , user - > context , sizeof ( pvt - > context ) - 1 ) ;
2003-04-11 20:28:25 +00:00
}
2004-10-04 10:13:01 +00:00
pvt - > exten [ 0 ] = ' i ' ;
pvt - > exten [ 1 ] = ' \0 ' ;
2004-05-20 21:56:12 +00:00
ast_log ( LOG_ERROR , " Call from '%s' rejected due to non-matching IP address (%s)s \n " , user - > name , cd . sourceIp ) ;
2005-04-04 15:54:34 +00:00
return NULL ;
2003-03-31 20:26:08 +00:00
}
2003-03-31 19:26:15 +00:00
}
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > context , user - > context , sizeof ( pvt - > context ) - 1 ) ;
pvt - > bridge = user - > bridge ;
pvt - > nat = user - > nat ;
if ( ! ast_strlen_zero ( pvt - > cd . call_dest_e164 ) ) {
strncpy ( pvt - > exten , cd . call_dest_e164 , sizeof ( pvt - > exten ) - 1 ) ;
2003-03-31 07:13:36 +00:00
} else {
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > exten , cd . call_dest_alias , sizeof ( pvt - > exten ) - 1 ) ;
2003-03-31 07:13:36 +00:00
}
2004-05-03 22:19:03 +00:00
if ( ! ast_strlen_zero ( user - > accountcode ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( pvt - > accountcode , user - > accountcode , sizeof ( pvt - > accountcode ) - 1 ) ;
2003-04-11 04:07:22 +00:00
}
2004-10-22 19:04:02 +00:00
if ( user - > amaflags ) {
pvt - > amaflags = user - > amaflags ;
}
2004-12-15 23:24:13 +00:00
call_options = & user - > options ;
2003-03-31 07:13:36 +00:00
}
}
2004-12-15 23:24:13 +00:00
return call_options ;
2004-06-15 20:56:06 +00:00
}
2003-03-31 07:13:36 +00:00
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
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt = NULL ;
2004-06-15 20:56:06 +00:00
struct ast_channel * c = NULL ;
2004-09-19 16:53:01 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Preparing Asterisk to answer for %s \n " , token ) ;
2004-06-15 20:56:06 +00:00
/* Find the call or allocate a private structure if call not found */
2004-10-04 10:13:01 +00:00
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
2004-06-15 20:56:06 +00:00
ast_log ( LOG_ERROR , " Something is wrong: answer_call \n " ) ;
return 0 ;
}
2005-02-09 21:15:44 +00:00
/* Briefly lock call for oh323_new() */
ast_mutex_lock ( & pvt - > lock ) ;
2004-06-15 20:56:06 +00:00
/* allocate a channel and tell asterisk about it */
2004-10-04 10:13:01 +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
}
/**
* Call - back function to establish an outgoing H .323 call
*
* Returns 1 on success
*/
int setup_outgoing_call ( call_details_t cd )
{
return 1 ;
}
2004-05-20 07:07:18 +00:00
/**
* Call - back function to signal asterisk that the channel is ringing
* Returns nothing
*/
2004-09-19 16:53:01 +00:00
void chan_ringing ( unsigned call_reference , const char * token )
2004-05-20 07:07:18 +00:00
{
struct ast_channel * c = NULL ;
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt = NULL ;
2004-05-20 07:07:18 +00:00
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Ringing on %s \n " , token ) ;
2004-10-04 10:13:01 +00:00
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
2004-05-20 07:07:18 +00:00
ast_log ( LOG_ERROR , " Something is wrong: ringing \n " ) ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > lock ) ;
2004-10-04 10:13:01 +00:00
if ( ! pvt - > owner ) {
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2004-05-20 07:07:18 +00:00
ast_log ( LOG_ERROR , " Channel has no owner \n " ) ;
return ;
}
2005-04-04 15:54:34 +00:00
ast_mutex_lock ( & pvt - > owner - > lock ) ;
2004-10-04 10:13:01 +00:00
c = pvt - > owner ;
2004-05-20 07:07:18 +00:00
ast_setstate ( c , AST_STATE_RINGING ) ;
ast_queue_control ( c , AST_CONTROL_RINGING ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
ast_mutex_unlock ( & pvt - > lock ) ;
2004-05-20 07:07:18 +00:00
return ;
}
2003-03-31 07:13:36 +00:00
/**
* Call - back function to cleanup communication
* Returns nothing ,
*/
2005-04-04 15:54:34 +00:00
static void cleanup_connection ( call_details_t cd )
2003-03-31 07:13:36 +00:00
{
2004-10-04 10:13:01 +00:00
struct oh323_pvt * pvt = NULL ;
2003-03-31 07:13:36 +00:00
struct ast_rtp * rtp = NULL ;
2005-04-04 15:54:34 +00:00
ast_log ( LOG_DEBUG , " Cleaning connection to %s \n " , cd . call_token ) ;
2003-03-31 07:13:36 +00:00
2005-04-04 15:54:34 +00:00
while ( 1 ) {
pvt = find_call ( cd . call_reference , cd . call_token ) ;
if ( ! pvt ) {
return ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( ! pvt - > owner | | ! ast_mutex_trylock ( & pvt - > owner - > lock ) )
break ;
# if 1
# ifdef DEBUG_THREADS
ast_log ( LOG_NOTICE , " Avoiding H.323 destory deadlock on %s, locked at %ld/%d by %s (%s:%d) \n " , cd . call_token , pvt - > owner - > lock . thread , pvt - > owner - > lock . reentrancy , pvt - > owner - > lock . func , pvt - > owner - > lock . file , pvt - > owner - > lock . lineno ) ;
# else
ast_log ( LOG_NOTICE , " Avoiding H.323 destory deadlock on %s \n " , cd . call_token ) ;
# endif
# endif
ast_mutex_unlock ( & pvt - > lock ) ;
usleep ( 1 ) ;
2003-03-31 07:13:36 +00:00
}
2004-10-04 10:13:01 +00:00
if ( pvt - > rtp ) {
rtp = pvt - > rtp ;
pvt - > rtp = NULL ;
2003-03-31 07:13:36 +00:00
/* Immediately stop RTP */
ast_rtp_destroy ( rtp ) ;
}
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 ;
2003-03-31 07:13:36 +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 ;
2004-10-04 10:13:01 +00:00
ast_queue_hangup ( pvt - > owner ) ;
2005-04-04 15:54:34 +00:00
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
2004-10-04 10:13:01 +00:00
ast_mutex_unlock ( & pvt - > lock ) ;
2003-03-31 07:13:36 +00:00
return ;
}
2005-04-04 15:54:34 +00:00
static void hangup_connection ( unsigned int call_reference , const char * token , int cause )
{
struct oh323_pvt * pvt = NULL ;
ast_log ( LOG_DEBUG , " Hanging up connection to %s with cause %d \n " , token , cause ) ;
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
return ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( pvt - > owner & & ! ast_mutex_trylock ( & pvt - > owner - > lock ) ) {
pvt - > owner - > _softhangup | = AST_SOFTHANGUP_DEV ;
pvt - > owner - > hangupcause = pvt - > hangupcause = cause ;
ast_queue_hangup ( pvt - > owner ) ;
ast_mutex_unlock ( & pvt - > owner - > lock ) ;
}
else {
pvt - > needhangup = 1 ;
pvt - > hangupcause = cause ;
ast_log ( LOG_DEBUG , " Hangup for %s is pending \n " , token ) ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
}
2004-12-15 23:24:13 +00:00
void set_dtmf_payload ( unsigned call_reference , const char * token , int payload )
{
struct oh323_pvt * pvt = NULL ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " Setting DTMF payload to %d on %s \n " , payload , token ) ;
2004-12-15 23:24:13 +00:00
pvt = find_call ( call_reference , token ) ;
if ( ! pvt ) {
return ;
}
ast_mutex_lock ( & pvt - > lock ) ;
if ( pvt - > rtp ) {
ast_rtp_set_rtpmap_type ( pvt - > rtp , payload , " audio " , " telephone-event " ) ;
}
ast_mutex_unlock ( & pvt - > lock ) ;
2005-04-04 15:54:34 +00:00
if ( h323debug )
ast_log ( LOG_DEBUG , " DTMF payload on %s set to %d \n " , token , payload ) ;
2004-12-15 23:24:13 +00:00
}
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 ;
2004-10-22 19:04:02 +00:00
for ( ; ; ) {
2004-10-15 07:07:50 +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 ) {
if ( option_verbose > 0 ) {
ast_verbose ( VERBOSE_PREFIX_1 " Reloading H.323 \n " ) ;
}
h323_do_reload ( ) ;
}
2003-03-31 07:13:36 +00:00
/* Check for interfaces needing to be killed */
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & iflock ) ;
2003-03-31 07:13:36 +00:00
restartsearch :
oh323 = iflist ;
while ( oh323 ) {
if ( oh323 - > needdestroy ) {
__oh323_destroy ( oh323 ) ;
goto restartsearch ;
}
oh323 = oh323 - > next ;
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & iflock ) ;
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
}
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 )
{
2004-10-15 07:07:50 +00:00
pthread_attr_t attr ;
2003-03-31 07:13:36 +00:00
/* If we're supposed to be stopped -- stay stopped */
2004-10-15 07:07:50 +00:00
if ( monitor_thread = = AST_PTHREADT_STOP ) {
2003-03-31 07:13:36 +00:00
return 0 ;
2004-10-15 07:07:50 +00:00
}
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 ;
}
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 ) ;
2004-10-15 07:07:50 +00:00
} else {
pthread_attr_init ( & attr ) ;
pthread_attr_setdetachstate ( & attr , PTHREAD_CREATE_DETACHED ) ;
/* Start a new monitor */
if ( ast_pthread_create ( & monitor_thread , & attr , do_monitor , NULL ) < 0 ) {
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 ;
}
static int h323_do_trace ( int fd , int argc , char * argv [ ] )
{
2004-01-11 02:20:01 +00:00
if ( argc ! = 3 ) {
2003-03-31 07:13:36 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
h323_debug ( 1 , atoi ( argv [ 2 ] ) ) ;
ast_cli ( fd , " H.323 trace set to level %s \n " , argv [ 2 ] ) ;
return RESULT_SUCCESS ;
}
static int h323_no_trace ( int fd , int argc , char * argv [ ] )
{
2004-01-11 02:20:01 +00:00
if ( argc ! = 3 ) {
2003-03-31 07:13:36 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
h323_debug ( 0 , 0 ) ;
ast_cli ( fd , " H.323 trace disabled \n " ) ;
return RESULT_SUCCESS ;
}
static int h323_do_debug ( int fd , int argc , char * argv [ ] )
{
2004-01-11 02:20:01 +00:00
if ( argc ! = 2 ) {
2003-03-31 07:13:36 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
h323debug = 1 ;
ast_cli ( fd , " H323 debug enabled \n " ) ;
return RESULT_SUCCESS ;
}
static int h323_no_debug ( int fd , int argc , char * argv [ ] )
{
2004-01-11 02:20:01 +00:00
if ( argc ! = 3 ) {
2003-03-31 07:13:36 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
h323debug = 0 ;
ast_cli ( fd , " H323 Debug disabled \n " ) ;
return RESULT_SUCCESS ;
}
static int h323_gk_cycle ( int fd , int argc , char * argv [ ] )
{
2004-01-13 09:17:14 +00:00
return RESULT_SUCCESS ;
2004-01-13 09:24:26 +00:00
#if 0
2004-01-11 02:20:01 +00:00
if ( argc ! = 3 ) {
2003-03-31 07:13:36 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2003-03-31 07:13:36 +00:00
h323_gk_urq ( ) ;
/* 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 " ) ;
}
}
return RESULT_SUCCESS ;
2004-01-13 09:24:26 +00:00
# endif
2003-03-31 07:13:36 +00:00
}
2004-01-06 16:51:34 +00:00
static int h323_ep_hangup ( int fd , int argc , char * argv [ ] )
{
2004-01-11 02:20:01 +00:00
if ( argc ! = 3 ) {
2004-01-06 16:51:34 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2004-01-06 16:51:34 +00:00
if ( h323_soft_hangup ( argv [ 2 ] ) ) {
ast_verbose ( VERBOSE_PREFIX_3 " Hangup succeeded on %s \n " , argv [ 2 ] ) ;
} else {
ast_verbose ( VERBOSE_PREFIX_3 " Hangup failed for %s \n " , argv [ 2 ] ) ;
}
return RESULT_SUCCESS ;
}
static int h323_tokens_show ( int fd , int argc , char * argv [ ] )
{
2004-01-11 02:20:01 +00:00
if ( argc ! = 3 ) {
2004-01-06 16:51:34 +00:00
return RESULT_SHOWUSAGE ;
2004-01-11 02:20:01 +00:00
}
2004-01-06 16:51:34 +00:00
h323_show_tokens ( ) ;
return RESULT_SUCCESS ;
}
2003-03-31 07:13:36 +00:00
static char trace_usage [ ] =
" Usage: h.323 trace <level num> \n "
" Enables H.323 stack tracing for debugging purposes \n " ;
static char no_trace_usage [ ] =
" Usage: h.323 no trace \n "
" Disables H.323 stack tracing for debugging purposes \n " ;
static char debug_usage [ ] =
" Usage: h.323 debug \n "
2004-10-28 06:06:58 +00:00
" Enables H.323 debug output \n " ;
2003-03-31 07:13:36 +00:00
static char no_debug_usage [ ] =
" Usage: h.323 no debug \n "
2004-10-28 06:06:58 +00:00
" Disables H.323 debug output \n " ;
2003-03-31 07:13:36 +00:00
static char show_codec_usage [ ] =
" Usage: h.323 show codec \n "
" Shows all enabled codecs \n " ;
static char show_cycle_usage [ ] =
" Usage: h.323 gk cycle \n "
2004-10-28 06:06:58 +00:00
" Manually re-register with the Gatekeper (Currently Disabled) \n " ;
2003-03-31 07:13:36 +00:00
2004-01-06 16:51:34 +00:00
static char show_hangup_usage [ ] =
" Usage: h.323 hangup <token> \n "
" Manually try to hang up call identified by <token> \n " ;
static char show_tokens_usage [ ] =
" Usage: h.323 show tokens \n "
" Print out all active call tokens \n " ;
2003-03-31 07:13:36 +00:00
2004-10-15 07:07:50 +00:00
static char h323_reload_usage [ ] =
" Usage: h323 reload \n "
" Reloads H.323 configuration from sip.conf \n " ;
2003-03-31 07:13:36 +00:00
static struct ast_cli_entry cli_trace =
{ { " h.323 " , " trace " , NULL } , h323_do_trace , " Enable H.323 Stack Tracing " , trace_usage } ;
static struct ast_cli_entry cli_no_trace =
{ { " h.323 " , " no " , " trace " , NULL } , h323_no_trace , " Disable H.323 Stack Tracing " , no_trace_usage } ;
static struct ast_cli_entry cli_debug =
2004-10-28 06:06:58 +00:00
{ { " h.323 " , " debug " , NULL } , h323_do_debug , " Enable H.323 debug " , debug_usage } ;
2003-03-31 07:13:36 +00:00
static struct ast_cli_entry cli_no_debug =
2004-10-28 06:06:58 +00:00
{ { " h.323 " , " no " , " debug " , NULL } , h323_no_debug , " Disable H.323 debug " , no_debug_usage } ;
2003-03-31 07:13:36 +00:00
static struct ast_cli_entry cli_show_codecs =
{ { " h.323 " , " show " , " codecs " , NULL } , h323_show_codec , " Show enabled codecs " , show_codec_usage } ;
static struct ast_cli_entry cli_gk_cycle =
{ { " h.323 " , " gk " , " cycle " , NULL } , h323_gk_cycle , " Manually re-register with the Gatekeper " , show_cycle_usage } ;
2004-01-06 16:51:34 +00:00
static struct ast_cli_entry cli_hangup_call =
2004-10-27 20:02:35 +00:00
{ { " h.323 " , " hangup " , NULL } , h323_ep_hangup , " Manually try to hang up a call " , show_hangup_usage } ;
2004-01-06 16:51:34 +00:00
static struct ast_cli_entry cli_show_tokens =
2004-10-27 20:02:35 +00:00
{ { " h.323 " , " show " , " tokens " , NULL } , h323_tokens_show , " Show all active call tokens " , show_tokens_usage } ;
2004-03-20 14:25:39 +00:00
2003-09-27 02:52:05 +00:00
int reload_config ( void )
2004-10-15 07:07:50 +00:00
{
2003-03-31 07:13:36 +00:00
int format ;
struct ast_config * cfg ;
struct ast_variable * v ;
struct oh323_peer * peer = NULL ;
struct oh323_user * user = NULL ;
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 ;
2004-04-05 20:45:14 +00:00
char * utype ;
2003-03-31 07:13:36 +00:00
2005-01-25 06:10:20 +00:00
cfg = ast_config_load ( config ) ;
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 ;
2003-03-31 07:13:36 +00:00
}
2003-12-18 19:48:42 +00:00
/* fire up the H.323 Endpoint */
if ( ! h323_end_point_exist ( ) ) {
2004-10-04 10:13:01 +00:00
h323_end_point_create ( ) ;
2003-12-18 19:48:42 +00:00
}
2004-10-28 06:06:58 +00:00
h323debug = 0 ;
2003-03-31 07:13:36 +00:00
dtmfmode = H323_DTMF_RFC2833 ;
memset ( & bindaddr , 0 , sizeof ( bindaddr ) ) ;
2004-12-15 23:24:13 +00:00
memset ( & global_options , 0 , sizeof ( global_options ) ) ;
global_options . dtmfcodec = 101 ;
2003-03-31 07:13:36 +00:00
v = ast_variable_browse ( cfg , " general " ) ;
while ( v ) {
/* 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 ) ) ;
}
} else if ( ! strcasecmp ( v - > name , " allow " ) ) {
format = ast_getformatbyname ( v - > value ) ;
if ( format < 1 )
ast_log ( LOG_WARNING , " Cannot allow unknown format '%s' \n " , v - > value ) ;
else
capability | = format ;
} else if ( ! strcasecmp ( v - > name , " disallow " ) ) {
format = ast_getformatbyname ( v - > value ) ;
if ( format < 1 )
ast_log ( LOG_WARNING , " Cannot disallow unknown format '%s' \n " , v - > value ) ;
else
capability & = ~ format ;
} else if ( ! strcasecmp ( v - > name , " tos " ) ) {
2004-10-28 06:06:58 +00:00
if ( sscanf ( v - > value , " %i " , & format ) ) {
2003-03-31 07:13:36 +00:00
tos = format & 0xff ;
2004-10-22 19:04:02 +00:00
} else if ( ! strcasecmp ( v - > value , " lowdelay " ) ) {
2003-03-31 07:13:36 +00:00
tos = IPTOS_LOWDELAY ;
2004-10-22 19:04:02 +00:00
} else if ( ! strcasecmp ( v - > value , " throughput " ) ) {
2003-03-31 07:13:36 +00:00
tos = IPTOS_THROUGHPUT ;
2004-10-22 19:04:02 +00:00
} else if ( ! strcasecmp ( v - > value , " reliability " ) ) {
2003-03-31 07:13:36 +00:00
tos = IPTOS_RELIABILITY ;
2004-10-22 19:04:02 +00:00
} else if ( ! strcasecmp ( v - > value , " mincost " ) ) {
2003-03-31 07:13:36 +00:00
tos = IPTOS_MINCOST ;
2004-10-22 19:04:02 +00:00
} else if ( ! strcasecmp ( v - > value , " none " ) ) {
2003-03-31 07:13:36 +00:00
tos = 0 ;
2004-10-22 19:04:02 +00:00
} else {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none' \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 ;
usingGk = 0 ;
} else if ( ! strcasecmp ( v - > value , " DISCOVER " ) ) {
gatekeeper_disable = 0 ;
gatekeeper_discover = 1 ;
usingGk = 1 ;
} else {
gatekeeper_disable = 0 ;
usingGk = 1 ;
2004-10-04 10:13:01 +00:00
strncpy ( gatekeeper , v - > value , sizeof ( gatekeeper ) - 1 ) ;
2003-03-31 07:13:36 +00:00
}
} else if ( ! strcasecmp ( v - > name , " secret " ) ) {
2004-10-28 06:06:58 +00:00
strncpy ( secret , v - > value , sizeof ( secret ) - 1 ) ;
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 " ) ) {
2004-10-04 10:13:01 +00:00
strncpy ( default_context , v - > value , sizeof ( default_context ) - 1 ) ;
2004-10-28 06:06:58 +00:00
ast_verbose ( VERBOSE_PREFIX_2 " Setting default context to %s \n " , default_context ) ;
2003-03-31 07:13:36 +00:00
} else if ( ! strcasecmp ( v - > name , " dtmfmode " ) ) {
2004-10-28 06:06:58 +00:00
if ( ! strcasecmp ( v - > value , " inband " ) ) {
dtmfmode = H323_DTMF_INBAND ;
} else if ( ! strcasecmp ( v - > value , " rfc2833 " ) ) {
2003-03-31 07:13:36 +00:00
dtmfmode = H323_DTMF_RFC2833 ;
2004-10-28 06:06:58 +00:00
} else {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_WARNING , " Unknown dtmf mode '%s', using rfc2833 \n " , v - > value ) ;
dtmfmode = H323_DTMF_RFC2833 ;
}
2004-12-15 23:24:13 +00:00
} else if ( ! strcasecmp ( v - > name , " dtmfcodec " ) ) {
global_options . dtmfcodec = atoi ( v - > value ) ;
2003-12-09 05:14:23 +00:00
} else if ( ! strcasecmp ( v - > name , " UserByAlias " ) ) {
userbyalias = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " bridge " ) ) {
2004-09-30 19:36:46 +00:00
bridging = ast_true ( v - > value ) ;
2004-07-17 19:38:30 +00:00
} else if ( ! strcasecmp ( v - > name , " noFastStart " ) ) {
2004-12-15 23:24:13 +00:00
global_options . noFastStart = ast_true ( v - > value ) ;
2004-07-17 19:38:30 +00:00
} else if ( ! strcasecmp ( v - > name , " noH245Tunneling " ) ) {
2004-12-15 23:24:13 +00:00
global_options . noH245Tunneling = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " noSilenceSuppression " ) ) {
global_options . noSilenceSuppression = ast_true ( v - > value ) ;
2004-07-17 19:38:30 +00:00
}
2003-03-31 07:13:36 +00:00
v = v - > next ;
}
cat = ast_category_browse ( cfg , NULL ) ;
while ( cat ) {
if ( strcasecmp ( cat , " general " ) ) {
utype = ast_variable_retrieve ( cfg , cat , " type " ) ;
if ( utype ) {
if ( ! strcasecmp ( utype , " user " ) | | ! strcasecmp ( utype , " friend " ) ) {
user = build_user ( cat , ast_variable_browse ( cfg , cat ) ) ;
if ( user ) {
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & userl . lock ) ;
2003-03-31 07:13:36 +00:00
user - > next = userl . users ;
userl . users = user ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & userl . lock ) ;
2003-03-31 07:13:36 +00:00
}
} else if ( ! strcasecmp ( utype , " peer " ) | | ! strcasecmp ( utype , " friend " ) ) {
peer = build_peer ( cat , ast_variable_browse ( cfg , cat ) ) ;
if ( peer ) {
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
peer - > next = peerl . peers ;
peerl . peers = peer ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
}
2004-10-28 06:06:58 +00:00
} else if ( ! strcasecmp ( utype , " h323 " ) | | ! strcasecmp ( utype , " alias " ) ) {
2003-03-31 07:13:36 +00:00
alias = build_alias ( cat , ast_variable_browse ( cfg , cat ) ) ;
if ( alias ) {
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & aliasl . lock ) ;
2003-03-31 07:13:36 +00:00
alias - > next = aliasl . aliases ;
aliasl . aliases = alias ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & aliasl . lock ) ;
2003-03-31 07:13:36 +00:00
}
} else {
ast_log ( LOG_WARNING , " Unknown type '%s' for '%s' in %s \n " , utype , cat , config ) ;
}
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
}
cat = ast_category_browse ( cfg , cat ) ;
}
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*/
while ( alias ) {
if ( h323_set_alias ( alias ) ) {
ast_log ( LOG_ERROR , " Alias %s rejected by endpoint \n " , alias - > name ) ;
return - 1 ;
}
alias = alias - > next ;
}
2004-10-28 06:06:58 +00:00
/* Add our capabilities */
2004-07-30 20:01:58 +00:00
ast_mutex_lock ( & caplock ) ;
2004-10-28 06:06:58 +00:00
if ( h323_set_capability ( capability , dtmfmode ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Capabilities failure, this is bad. \n " ) ;
2004-07-30 20:01:58 +00:00
ast_mutex_unlock ( & caplock ) ;
2003-03-31 07:13:36 +00:00
return - 1 ;
2004-07-30 20:01:58 +00:00
}
ast_mutex_unlock ( & caplock ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
void delete_users ( void )
{
struct oh323_user * user , * userlast ;
struct oh323_peer * peer ;
/* Delete all users */
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & userl . lock ) ;
2003-03-31 07:13:36 +00:00
for ( user = userl . users ; user ; ) {
userlast = user ;
user = user - > next ;
free ( userlast ) ;
}
userl . users = NULL ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & userl . lock ) ;
ast_mutex_lock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
for ( peer = peerl . peers ; peer ; ) {
/* Assume all will be deleted, and we'll find out for sure later */
peer - > delme = 1 ;
peer = peer - > next ;
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
}
void delete_aliases ( void )
{
struct oh323_alias * alias , * aliaslast ;
2004-03-20 14:25:39 +00:00
2003-03-31 07:13:36 +00:00
/* Delete all users */
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & aliasl . lock ) ;
2003-03-31 07:13:36 +00:00
for ( alias = aliasl . aliases ; alias ; ) {
aliaslast = alias ;
alias = alias - > next ;
free ( aliaslast ) ;
}
aliasl . aliases = NULL ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & aliasl . lock ) ;
2003-03-31 07:13:36 +00:00
}
void prune_peers ( void )
{
/* Prune peers who still are supposed to be deleted */
struct oh323_peer * peer , * peerlast , * peernext ;
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
peerlast = NULL ;
for ( peer = peerl . peers ; peer ; ) {
peernext = peer - > next ;
if ( peer - > delme ) {
free ( peer ) ;
2004-10-28 06:06:58 +00:00
if ( peerlast ) {
2003-03-31 07:13:36 +00:00
peerlast - > next = peernext ;
2004-10-28 06:06:58 +00:00
} else {
2003-03-31 07:13:36 +00:00
peerl . peers = peernext ;
2004-10-28 06:06:58 +00:00
}
} else {
2003-03-31 07:13:36 +00:00
peerlast = peer ;
2004-10-28 06:06:58 +00:00
}
peer = peernext ;
2003-03-31 07:13:36 +00:00
}
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & peerl . lock ) ;
2003-03-31 07:13:36 +00:00
}
2004-10-15 07:07:50 +00:00
static int h323_reload ( int fd , int argc , char * argv [ ] )
{
ast_mutex_lock ( & h323_reload_lock ) ;
if ( h323_reloading ) {
ast_verbose ( " Previous H.323 reload not yet done \n " ) ;
} else {
h323_reloading = 1 ;
}
ast_mutex_unlock ( & h323_reload_lock ) ;
restart_monitor ( ) ;
return 0 ;
}
static int h323_do_reload ( void )
2003-03-31 07:13:36 +00:00
{
delete_users ( ) ;
2004-10-15 07:07:50 +00:00
delete_aliases ( ) ;
prune_peers ( ) ;
reload_config ( ) ;
restart_monitor ( ) ;
return 0 ;
}
2003-03-31 07:13:36 +00:00
2004-10-15 07:07:50 +00:00
int reload ( void )
{
return h323_reload ( 0 , 0 , NULL ) ;
2003-03-31 07:13:36 +00:00
}
2004-10-15 07:07:50 +00:00
static struct ast_cli_entry cli_h323_reload =
{ { " h.323 " , " reload " , NULL } , h323_reload , " Reload H.323 configuration " , h323_reload_usage } ;
2003-03-31 07:13:36 +00:00
static struct ast_rtp * oh323_get_rtp_peer ( struct ast_channel * chan )
{
struct oh323_pvt * p ;
2005-03-04 06:47:24 +00:00
p = ( struct oh323_pvt * ) chan - > tech_pvt ;
2003-08-25 09:54:36 +00:00
if ( p & & p - > rtp & & p - > bridge ) {
2003-03-31 07:13:36 +00:00
return p - > rtp ;
2003-08-25 09:54:36 +00:00
}
2003-03-31 07:13:36 +00:00
return NULL ;
}
2003-07-01 19:11:37 +00:00
static struct ast_rtp * oh323_get_vrtp_peer ( struct ast_channel * chan )
2003-03-31 07:13:36 +00:00
{
2003-07-01 19:11:37 +00:00
return NULL ;
}
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 " ;
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 ;
}
}
2004-05-27 04:18:46 +00:00
static int oh323_set_rtp_peer ( struct ast_channel * chan , struct ast_rtp * rtp , struct ast_rtp * vrtp , int codecs )
2003-07-01 19:11:37 +00:00
{
/* XXX Deal with Video */
2003-03-31 07:13:36 +00:00
struct oh323_pvt * p ;
struct sockaddr_in them ;
struct sockaddr_in us ;
2003-08-25 09:54:36 +00:00
char * mode ;
2004-06-30 16:56:51 +00:00
char iabuf [ INET_ADDRSTRLEN ] ;
2003-08-25 09:54:36 +00:00
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
2004-10-28 06:06:58 +00:00
mode = convertcap ( chan - > writeformat ) ;
2005-03-04 06:47:24 +00:00
p = ( struct oh323_pvt * ) chan - > tech_pvt ;
2003-03-31 07:13:36 +00:00
if ( ! p ) {
ast_log ( LOG_ERROR , " No Private Structure, this is bad \n " ) ;
return - 1 ;
}
ast_rtp_get_peer ( rtp , & them ) ;
2003-08-25 09:54:36 +00:00
ast_rtp_get_us ( rtp , & us ) ;
2004-06-29 12:56:46 +00:00
h323_native_bridge ( p - > cd . call_token , ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , them . sin_addr ) , mode ) ;
2003-03-31 07:13:36 +00:00
return 0 ;
}
static struct ast_rtp_protocol oh323_rtp = {
2005-03-04 06:47:24 +00:00
. type = type ,
. get_rtp_info = oh323_get_rtp_peer ,
. get_vrtp_info = oh323_get_vrtp_peer ,
. set_rtp_peer = oh323_set_rtp_peer ,
2003-03-31 07:13:36 +00:00
} ;
int load_module ( )
{
int res ;
2004-06-22 17:42:14 +00:00
ast_mutex_init ( & userl . lock ) ;
ast_mutex_init ( & peerl . lock ) ;
ast_mutex_init ( & aliasl . lock ) ;
2004-10-15 07:07:50 +00:00
sched = sched_context_create ( ) ;
if ( ! sched ) {
ast_log ( LOG_WARNING , " Unable to create schedule context \n " ) ;
}
io = io_context_create ( ) ;
if ( ! io ) {
ast_log ( LOG_WARNING , " Unable to create I/O context \n " ) ;
}
2003-03-31 07:13:36 +00:00
res = reload_config ( ) ;
2003-12-10 23:34:47 +00:00
if ( res ) {
return 0 ;
} else {
/* Make sure we can register our channel type */
2005-03-04 06:47:24 +00:00
if ( ast_channel_register ( & oh323_tech ) ) {
2003-03-31 07:13:36 +00:00
ast_log ( LOG_ERROR , " Unable to register channel class %s \n " , type ) ;
h323_end_process ( ) ;
return - 1 ;
}
ast_cli_register ( & cli_debug ) ;
ast_cli_register ( & cli_no_debug ) ;
ast_cli_register ( & cli_trace ) ;
ast_cli_register ( & cli_no_trace ) ;
ast_cli_register ( & cli_show_codecs ) ;
2004-01-13 08:56:02 +00:00
ast_cli_register ( & cli_gk_cycle ) ;
2004-01-06 16:51:34 +00:00
ast_cli_register ( & cli_hangup_call ) ;
ast_cli_register ( & cli_show_tokens ) ;
2004-10-15 07:07:50 +00:00
ast_cli_register ( & cli_h323_reload ) ;
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 */
h323_callback_register ( setup_incoming_call ,
2004-01-13 03:07:15 +00:00
setup_outgoing_call ,
2004-10-10 12:20:18 +00:00
external_rtp_create ,
2004-01-13 03:07:15 +00:00
setup_rtp_connection ,
cleanup_connection ,
2004-05-20 07:07:18 +00:00
chan_ringing ,
2004-01-13 03:07:15 +00:00
connection_made ,
2004-06-15 20:56:06 +00:00
send_digit ,
2004-12-15 23:24:13 +00:00
answer_call ,
progress ,
2005-04-04 15:54:34 +00:00
set_dtmf_payload ,
hangup_connection ) ;
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 " ) ;
return - 1 ;
}
/* 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 " ) ;
2003-10-21 13:12:30 +00:00
return 0 ;
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
2003-03-31 07:13:36 +00:00
int unload_module ( )
{
struct oh323_pvt * p , * pl ;
2004-10-22 19:04:02 +00:00
/* unregister commands */
ast_cli_unregister ( & cli_debug ) ;
ast_cli_unregister ( & cli_no_debug ) ;
ast_cli_unregister ( & cli_trace ) ;
ast_cli_unregister ( & cli_no_trace ) ;
ast_cli_unregister ( & cli_show_codecs ) ;
ast_cli_unregister ( & cli_gk_cycle ) ;
ast_cli_unregister ( & cli_hangup_call ) ;
ast_cli_unregister ( & cli_show_tokens ) ;
ast_cli_unregister ( & cli_h323_reload ) ;
ast_rtp_proto_unregister ( & oh323_rtp ) ;
2005-03-04 06:47:24 +00:00
ast_channel_unregister ( & oh323_tech ) ;
2003-03-31 07:13:36 +00:00
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 ) ) {
2004-03-15 07:51:22 +00:00
if ( monitor_thread & & ( monitor_thread ! = AST_PTHREADT_STOP ) ) {
2004-10-28 06:06:58 +00:00
/* this causes a seg, anyone know why? */
pthread_cancel ( monitor_thread ) ;
2004-01-13 03:07:15 +00:00
pthread_kill ( monitor_thread , SIGURG ) ;
pthread_join ( monitor_thread , NULL ) ;
}
2004-03-15 07:51:22 +00:00
monitor_thread = AST_PTHREADT_STOP ;
2004-01-13 03:07:15 +00:00
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 ) ;
2003-03-31 07:13:36 +00:00
free ( pl ) ;
}
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 ;
}
h323_gk_urq ( ) ;
h323_end_process ( ) ;
2004-10-22 19:04:02 +00:00
ast_mutex_destroy ( & userl . lock ) ;
ast_mutex_destroy ( & peerl . lock ) ;
2004-01-11 02:20:01 +00:00
return 0 ;
}
2003-03-31 07:13:36 +00:00
int usecount ( )
{
int res ;
2003-08-14 06:56:11 +00:00
ast_mutex_lock ( & usecnt_lock ) ;
2003-03-31 07:13:36 +00:00
res = usecnt ;
2003-08-14 06:56:11 +00:00
ast_mutex_unlock ( & usecnt_lock ) ;
2003-03-31 07:13:36 +00:00
return res ;
}
char * description ( )
{
2005-03-08 23:11:23 +00:00
return ( char * ) desc ;
2003-03-31 07:13:36 +00:00
}
char * key ( )
{
return ASTERISK_GPL_KEY ;
}