@ -28,48 +28,6 @@
* \ ingroup channel_drivers
*/
/* FO: Changes
* - - add distinctive ring signalling ( part of RFC 3660 )
*/
/* JS: Changes
- - add support for the wildcard endpoint
- - seteable wildcard with wcardep on mgcp . conf
- - added package indicator on RQNT , i . e " dl " - - > " L/dl "
- - removed MDCX just before DLCX , do we need this ?
*/
/* JS: TODO
- - reload for wildcard endpoint probably buggy
- - when hf is notified we ' re sending CRCX after MDCX , without waiting for
OK on the MDCX which fails on Cisco IAD 24 XX
- - honour codec order , by now the lowest codec number in " allow " is the prefered
*/
/* SC: Changes
- - packet retransmit mechanism ( simplistic )
- - per endpoint / subchannel mgcp command sequencing .
- - better transaction handling
- - fixed some mem leaks
- - run - time configuration reload
- - distinguish CA and GW default MGCP ports
- - prevent clipping of DTMF tones in an established call
- - fixed a few crash scenarios in 3 - way
- - fix for a few cases where asterisk and MGW end - up in conflicting ep states
- - enclose numeric IP in [ ] for outgoing requests
*/
/* SC: TODO
- - piggyback support
- - responseAck support
- - enhance retransmit mechanism ( RTO calc . etc . )
- - embedded command support
*/
/* FS: Changes
- - fixed reload_config ( ) / do_monitor to stay responsive during reloads
*/
# include "asterisk.h"
ASTERISK_FILE_VERSION ( __FILE__ , " $Revision$ " )
@ -155,13 +113,13 @@ static const char config[] = "mgcp.conf";
# define MGCP_DTMF_INBAND (1 << 1)
# define MGCP_DTMF_HYBRID (1 << 2)
# define DEFAULT_MGCP_GW_PORT 2427 /* From RFC 2705 */
# define DEFAULT_MGCP_CA_PORT 2727 /* From RFC 2705 */
# define MGCP_MAX_PACKET 1500 /* Also from RFC 2543, should sub headers tho */
# define DEFAULT_RETRANS 1000 /* How frequently to retransmit */
# define MAX_RETRANS 5 /* Try only 5 times for retransmissions */
# define DEFAULT_MGCP_GW_PORT 2427 /* !< From RFC 2705 */
# define DEFAULT_MGCP_CA_PORT 2727 /* !< From RFC 2705 */
# define MGCP_MAX_PACKET 1500 /* !< Also from RFC 2543, should sub headers tho */
# define DEFAULT_RETRANS 1000 /* !< How frequently to retransmit */
# define MAX_RETRANS 5 /* !< Try only 5 times for retransmissions */
/* MGCP rtp stream modes */
/* ! MGCP rtp stream modes { */
# define MGCP_CX_SENDONLY 0
# define MGCP_CX_RECVONLY 1
# define MGCP_CX_SENDRECV 2
@ -169,6 +127,7 @@ static const char config[] = "mgcp.conf";
# define MGCP_CX_CONFERENCE 3
# define MGCP_CX_MUTE 4
# define MGCP_CX_INACTIVE 4
/*! } */
static char * mgcp_cxmodes [ ] = {
" sendonly " ,
@ -178,16 +137,17 @@ static char *mgcp_cxmodes[] = {
" inactive "
} ;
/* SC: MGCP commands */
# define MGCP_CMD_EPCF 0
# define MGCP_CMD_CRCX 1
# define MGCP_CMD_MDCX 2
# define MGCP_CMD_DLCX 3
# define MGCP_CMD_RQNT 4
# define MGCP_CMD_NTFY 5
# define MGCP_CMD_AUEP 6
# define MGCP_CMD_AUCX 7
# define MGCP_CMD_RSIP 8
enum {
MGCP_CMD_EPCF ,
MGCP_CMD_CRCX ,
MGCP_CMD_MDCX ,
MGCP_CMD_DLCX ,
MGCP_CMD_RQNT ,
MGCP_CMD_NTFY ,
MGCP_CMD_AUEP ,
MGCP_CMD_AUCX ,
MGCP_CMD_RSIP
} ;
static char context [ AST_MAX_EXTENSION ] = " default " ;
@ -199,39 +159,22 @@ static char cid_name[AST_MAX_EXTENSION] = "";
static int dtmfmode = 0 ;
static int nat = 0 ;
/* Not used. Dosn't hurt for us to always send cid */
/* to the mgcp box. */
/*static int use_callerid = 1;*/
/*static int cur_signalling = -1;*/
/*static unsigned int cur_group = 0;*/
static ast_group_t cur_callergroup = 0 ;
static ast_group_t cur_pickupgroup = 0 ;
/* XXX Is this needed? */
/* Doesn't look like the dsp stuff for */
/* dtmfmode is actually hooked up. */
/*static int relaxdtmf = 0;*/
static int tos = 0 ;
static int immediate = 0 ;
static int callwaiting = 0 ;
/* Not used. Dosn't hurt for us to always send cid */
/* to the mgcp box. */
/*static int callwaitingcallerid = 0;*/
/*static int hidecallerid = 0;*/
static int callreturn = 0 ;
static int slowsequence = 0 ;
static int threewaycalling = 0 ;
/* This is for flashhook transfers */
/* ! This is for flashhook transfers */
static int transfer = 0 ;
static int cancallforward = 0 ;
@ -240,10 +183,6 @@ static int singlepath = 0;
static int canreinvite = CANREINVITE ;
/*static int busycount = 3;*/
/*static int callprogress = 0;*/
static char accountcode [ AST_MAX_ACCOUNT_CODE ] = " " ;
static char mailbox [ AST_MAX_EXTENSION ] ;
@ -252,26 +191,25 @@ static int amaflags = 0;
static int adsi = 0 ;
/* SC: transaction id should always be positive */
static unsigned int oseq ;
/* Wait up to 16 seconds for first digit (FXO logic) */
/* ! Wait up to 16 seconds for first digit (FXO logic) */
static int firstdigittimeout = 16000 ;
/* How long to wait for following digits (FXO logic) */
/* ! How long to wait for following digits (FXO logic) */
static int gendigittimeout = 8000 ;
/* How long to wait for an extra digit, if there is an ambiguous match */
/* ! How long to wait for an extra digit, if there is an ambiguous match */
static int matchdigittimeout = 3000 ;
/* Protect the monitoring thread, so only one process can kill or start it, and not
when it ' s doing something critical . */
/* ! Protect the monitoring thread, so only one process can kill or start it, and not
when it ' s doing something critical . */
AST_MUTEX_DEFINE_STATIC ( netlock ) ;
AST_MUTEX_DEFINE_STATIC ( monlock ) ;
/* This is the thread for the monitor which checks for input on the channels
which are not currently in use . */
/* ! This is the thread for the monitor which checks for input on the channels
which are not currently in use . */
static pthread_t monitor_thread = AST_PTHREADT_NULL ;
static int restart_monitor ( void ) ;
@ -287,8 +225,8 @@ static int mgcpdebug = 0;
static struct sched_context * sched ;
static struct io_context * io ;
/* The private structures of the mgcp channels are linked for
selecting outgoing channels */
/* ! The private structures of the mgcp channels are linked for
! selecting outgoing channels */
# define MGCP_MAX_HEADERS 64
# define MGCP_MAX_LINES 64
@ -304,21 +242,11 @@ struct mgcp_request {
int lines ; /*!< SDP Content */
char * line [ MGCP_MAX_LINES ] ;
char data [ MGCP_MAX_PACKET ] ;
int cmd ; /*!< SC: int version of verb = command */
unsigned int trid ; /*!< SC: int version of identifier = transaction id */
struct mgcp_request * next ; /*!< SC: next in the queue */
int cmd ; /*!< int version of verb = command */
unsigned int trid ; /*!< int version of identifier = transaction id */
struct mgcp_request * next ; /*!< next in the queue */
} ;
/* SC: obsolete
static struct mgcp_pkt {
int retrans ;
struct mgcp_endpoint * owner ;
int packetlen ;
char data [ MGCP_MAX_PACKET ] ;
struct mgcp_pkt * next ;
} * packets = NULL ;
*/
/*! \brief mgcp_message: MGCP message for queuing up */
struct mgcp_message {
struct mgcp_endpoint * owner_ep ;
@ -331,7 +259,7 @@ struct mgcp_message {
char buf [ 0 ] ;
} ;
# define RESPONSE_TIMEOUT 30 /* in seconds */
# define RESPONSE_TIMEOUT 30 /* !< in seconds */
struct mgcp_response {
time_t whensent ;
@ -347,7 +275,7 @@ struct mgcp_response {
# define SUB_ALT 1
struct mgcp_subchannel {
/* SC: subchannel magic string.
/* ! subchannel magic string.
Needed to prove that any subchannel pointer passed by asterisk
really points to a valid subchannel memory area .
Ugly . . But serves the purpose for the time being .
@ -360,18 +288,18 @@ struct mgcp_subchannel {
struct mgcp_endpoint * parent ;
struct ast_rtp * rtp ;
struct sockaddr_in tmpdest ;
char txident [ 80 ] ; /* FIXME SC: txident is replaced by rqnt_ident in endpoint.
char txident [ 80 ] ; /* ! \todo FIXME txident is replaced by rqnt_ident in endpoint.
This should be obsoleted */
char cxident [ 80 ] ;
char callid [ 80 ] ;
int cxmode ;
struct mgcp_request * cx_queue ; /*!< SC: pending CX commands */
ast_mutex_t cx_queue_lock ; /*!< SC: CX queue lock */
struct mgcp_request * cx_queue ; /*!< pending CX commands */
ast_mutex_t cx_queue_lock ; /*!< CX queue lock */
int nat ;
int iseq ; /* Not used? RTP? */
int iseq ; /* !< Not used? RTP? */
int outgoing ;
int alreadygone ;
struct mgcp_subchannel * next ; /* for out circular linked list */
struct mgcp_subchannel * next ; /* !< for out circular linked list */
} ;
# define MGCP_ONHOOK 1
@ -423,13 +351,13 @@ struct mgcp_endpoint {
int immediate ;
int hookstate ;
int adsi ;
char rqnt_ident [ 80 ] ; /*!< SC: request identifier */
struct mgcp_request * rqnt_queue ; /*!< SC: pending RQNT commands */
char rqnt_ident [ 80 ] ; /*!< request identifier */
struct mgcp_request * rqnt_queue ; /*!< pending RQNT commands */
ast_mutex_t rqnt_queue_lock ;
struct mgcp_request * cmd_queue ; /*!< SC: pending commands other than RQNT */
struct mgcp_request * cmd_queue ; /*!< pending commands other than RQNT */
ast_mutex_t cmd_queue_lock ;
int delme ; /*!< SC: needed for reload */
int needaudit ; /*!< SC: needed for reload */
int delme ; /*!< needed for reload */
int needaudit ; /*!< needed for reload */
struct ast_dsp * dsp ; /*!< XXX Should there be a dsp/subchannel? XXX */
/* owner is tracked on the subchannels, and the *sub indicates whos in charge */
/* struct ast_channel *owner; */
@ -443,7 +371,7 @@ struct mgcp_endpoint {
static struct mgcp_gateway {
/* A gateway containing one or more endpoints */
char name [ 80 ] ;
int isnamedottedip ; /*!< SC: is the name FQDN or dotted ip */
int isnamedottedip ; /*!< is the name FQDN or dotted ip */
struct sockaddr_in addr ;
struct sockaddr_in defaddr ;
struct in_addr ourip ;
@ -451,17 +379,17 @@ static struct mgcp_gateway {
int expire ; /*!< XXX Should we ever expire dynamic registrations? XXX */
struct mgcp_endpoint * endpoints ;
struct ast_ha * ha ;
/* SC: obsolete
/* obsolete
time_t lastouttime ;
int lastout ;
int messagepending ;
*/
/* JS: Wildcard endpoint name */
/* Wildcard endpoint name */
char wcardep [ 30 ] ;
struct mgcp_message * msgs ; /*!< SC: gw msg queue */
ast_mutex_t msgs_lock ; /*!< SC: queue lock */
int retransid ; /*!< SC: retrans timer id */
int delme ; /*!< SC: needed for reload */
struct mgcp_message * msgs ; /*!< gw msg queue */
ast_mutex_t msgs_lock ; /*!< queue lock */
int retransid ; /*!< retrans timer id */
int delme ; /*!< needed for reload */
struct mgcp_response * responses ;
struct mgcp_gateway * next ;
} * gateways ;
@ -552,7 +480,7 @@ static int unalloc_sub(struct mgcp_subchannel *sub)
return 0 ;
}
/* SC: modified for new transport mechanism */
/* modified for new transport mechanism */
static int __mgcp_xmit ( struct mgcp_gateway * gw , char * data , int len )
{
int res ;
@ -594,7 +522,7 @@ static int send_response(struct mgcp_subchannel *sub, struct mgcp_request *req)
return res ;
}
/* SC: modified for new transport framework */
/* modified for new transport framework */
static void dump_queue ( struct mgcp_gateway * gw , struct mgcp_endpoint * p )
{
struct mgcp_message * cur , * q = NULL , * w , * prev ;
@ -736,7 +664,7 @@ static int retrans_pkt(void *data)
return res ;
}
/* SC: modified for the new transaction mechanism */
/* modified for the new transaction mechanism */
static int mgcp_postrequest ( struct mgcp_endpoint * p , struct mgcp_subchannel * sub ,
char * data , int len , unsigned int seqno )
{
@ -802,7 +730,7 @@ static int mgcp_postrequest(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
return 0 ;
}
/* SC: modified for new transport */
/* modified for new transport */
static int send_request ( struct mgcp_endpoint * p , struct mgcp_subchannel * sub ,
struct mgcp_request * req , unsigned int seqno )
{
@ -875,7 +803,7 @@ static int send_request(struct mgcp_endpoint *p, struct mgcp_subchannel *sub,
}
}
/* XXX SC: find tail. We could also keep tail in the data struct for faster access */
/* XXX find tail. We could also keep tail in the data struct for faster access */
for ( t = * queue ; t & & t - > next ; t = t - > next ) ;
r - > next = NULL ;
@ -1004,7 +932,7 @@ static int mgcp_hangup(struct ast_channel *ast)
}
if ( ( p - > dtmfmode & MGCP_DTMF_INBAND ) & & p - > dsp ) {
/* SC: check whether other channel is active. */
/* check whether other channel is active. */
if ( ! sub - > next - > owner ) {
if ( p - > dtmfmode & MGCP_DTMF_HYBRID )
p - > dtmfmode & = ~ MGCP_DTMF_INBAND ;
@ -1056,10 +984,10 @@ static int mgcp_hangup(struct ast_channel *ast)
sub - > rtp = NULL ;
}
/* SC: Decrement use count */
/* Decrement use count */
ast_atomic_fetchadd_int ( & __mod_desc - > usecnt , - 1 ) ;
ast_update_use_count ( ) ;
/* SC: Decrement use count */
/* Decrement use count */
if ( ( p - > hookstate = = MGCP_ONHOOK ) & & ( ! sub - > next - > rtp ) ) {
p - > hidecallerid = 0 ;
@ -1101,7 +1029,7 @@ static int mgcp_show_endpoints(int fd, int argc, char *argv[])
e = g - > endpoints ;
ast_cli ( fd , " Gateway '%s' at %s (%s) \n " , g - > name , g - > addr . sin_addr . s_addr ? ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , g - > addr . sin_addr ) : ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , g - > defaddr . sin_addr ) , g - > dynamic ? " Dynamic " : " Static " ) ;
while ( e ) {
/* JS: Don't show wilcard endpoint */
/* Don't show wilcard endpoint */
if ( strcmp ( e - > name , g - > wcardep ) ! = 0 )
ast_cli ( fd , " -- '%s@%s in '%s' is %s \n " , e - > name , g - > name , e - > context , e - > sub - > owner ? " active " : " idle " ) ;
hasendpoints = 1 ;
@ -1197,7 +1125,7 @@ static int mgcp_answer(struct ast_channel *ast)
} else {
transmit_modify_request ( sub ) ;
}
/* SC: verbose level check */
/* verbose level check */
if ( option_verbose > 2 ) {
ast_verbose ( VERBOSE_PREFIX_3 " MGCP mgcp_answer(%s) on %s@%s-%d \n " ,
ast - > name , p - > name , p - > parent - > name , sub - > id ) ;
@ -1428,9 +1356,15 @@ static int mgcp_indicate(struct ast_channel *ast, int ind, const void *data, siz
case AST_CONTROL_CONGESTION :
transmit_notify_request ( sub , " G/cg " ) ;
break ;
case AST_CONTROL_HOLD :
ast_moh_start ( ast , data , NULL ) ;
break ;
case AST_CONTROL_UNHOLD :
ast_moh_stop ( ast ) ;
break ;
case - 1 :
transmit_notify_request ( sub , " " ) ;
break ;
break ;
default :
ast_log ( LOG_WARNING , " Don't know how to indicate condition %d \n " , ind ) ;
res = - 1 ;
@ -1458,7 +1392,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
if ( i - > dtmfmode & ( MGCP_DTMF_INBAND | MGCP_DTMF_HYBRID ) ) {
i - > dsp = ast_dsp_new ( ) ;
ast_dsp_set_features ( i - > dsp , DSP_FEATURE_DTMF_DETECT ) ;
/* SC: this is to prevent clipping of dtmf tones during dsp processing */
/* this is to prevent clipping of dtmf tones during dsp processing */
ast_dsp_digitmode ( i - > dsp , DSP_DIGITMODE_NOQUELCH ) ;
} else {
i - > dsp = NULL ;
@ -1496,7 +1430,7 @@ static struct ast_channel *mgcp_new(struct mgcp_subchannel *sub, int state)
tmp = NULL ;
}
}
/* SC: verbose level check */
/* verbose level check */
if ( option_verbose > 2 ) {
ast_verbose ( VERBOSE_PREFIX_3 " MGCP mgcp_new(%s) created in state: %s \n " ,
tmp - > name , ast_state2str ( state ) ) ;
@ -1637,14 +1571,14 @@ static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, s
ast_verbose ( VERBOSE_PREFIX_3 " Registered MGCP gateway '%s' at %s port %d \n " , g - > name , ast_inet_ntoa ( iabuf , sizeof ( iabuf ) , g - > addr . sin_addr ) , ntohs ( g - > addr . sin_port ) ) ;
}
}
/* SC: not dynamic, check if the name matches */
/* not dynamic, check if the name matches */
else if ( name ) {
if ( strcasecmp ( g - > name , at ) ) {
g = g - > next ;
continue ;
}
}
/* SC: not dynamic, no name, check if the addr matches */
/* not dynamic, no name, check if the addr matches */
else if ( ! name & & sin ) {
if ( ( g - > addr . sin_addr . s_addr ! = sin - > sin_addr . s_addr ) | |
( g - > addr . sin_port ! = sin - > sin_port ) ) {
@ -1662,7 +1596,7 @@ static struct mgcp_subchannel *find_subchannel_and_lock(char *name, int msgid, s
ast_log ( LOG_DEBUG , " Searching on %s@%s for subchannel \n " ,
p - > name , g - > name ) ;
if ( msgid ) {
#if 0 /* SC: new transport mech */
#if 0 /* new transport mech */
sub = p - > sub ;
do {
if ( option_debug )
@ -1971,7 +1905,7 @@ static int init_req(struct mgcp_endpoint *p, struct mgcp_request *req, char *ver
return - 1 ;
}
req - > header [ req - > headers ] = req - > data + req - > len ;
/* SC: check if we need brackets around the gw name */
/* check if we need brackets around the gw name */
if ( p - > parent - > isnamedottedip )
snprintf ( req - > header [ req - > headers ] , sizeof ( req - > data ) - req - > len , " %s %d %s@[%s] MGCP 1.0 \r \n " , verb , oseq , p - > name , p - > parent - > name ) ;
else
@ -2148,12 +2082,12 @@ static int transmit_modify_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
add_header ( & resp , " C " , sub - > callid ) ;
add_header ( & resp , " L " , local ) ;
add_header ( & resp , " M " , mgcp_cxmodes [ sub - > cxmode ] ) ;
/* SC: X header should not be sent. kept for compatibility */
/* X header should not be sent. kept for compatibility */
add_header ( & resp , " X " , sub - > txident ) ;
add_header ( & resp , " I " , sub - > cxident ) ;
/*add_header(&resp, "S", "");*/
add_sdp ( & resp , sub , rtp ) ;
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_MDCX ;
resp . trid = oseq ;
return send_request ( p , sub , & resp , oseq ) ; /* SC */
@ -2182,11 +2116,11 @@ static int transmit_connect_with_sdp(struct mgcp_subchannel *sub, struct ast_rtp
add_header ( & resp , " C " , sub - > callid ) ;
add_header ( & resp , " L " , local ) ;
add_header ( & resp , " M " , mgcp_cxmodes [ sub - > cxmode ] ) ;
/* SC: X header should not be sent. kept for compatibility */
/* X header should not be sent. kept for compatibility */
add_header ( & resp , " X " , sub - > txident ) ;
/*add_header(&resp, "S", "");*/
add_sdp ( & resp , sub , rtp ) ;
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_CRCX ;
resp . trid = oseq ;
return send_request ( p , sub , & resp , oseq ) ; /* SC */
@ -2215,7 +2149,7 @@ static int transmit_notify_request(struct mgcp_subchannel *sub, char *tone)
if ( ! ast_strlen_zero ( tone ) ) {
add_header ( & resp , " S " , tone ) ;
}
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_RQNT ;
resp . trid = oseq ;
return send_request ( p , NULL , & resp , oseq ) ; /* SC */
@ -2262,7 +2196,7 @@ static int transmit_notify_request_with_callerid(struct mgcp_subchannel *sub, ch
ast_verbose ( VERBOSE_PREFIX_3 " MGCP Asked to indicate tone: %s on %s@%s-%d in cxmode: %s \n " ,
tone2 , p - > name , p - > parent - > name , sub - > id , mgcp_cxmodes [ sub - > cxmode ] ) ;
}
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_RQNT ;
resp . trid = oseq ;
return send_request ( p , NULL , & resp , oseq ) ; /* SC */
@ -2285,7 +2219,7 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
reqprep ( & resp , p , " MDCX " ) ;
add_header ( & resp , " C " , sub - > callid ) ;
add_header ( & resp , " M " , mgcp_cxmodes [ sub - > cxmode ] ) ;
/* SC: X header should not be sent. kept for compatibility */
/* X header should not be sent. kept for compatibility */
add_header ( & resp , " X " , sub - > txident ) ;
add_header ( & resp , " I " , sub - > cxident ) ;
switch ( sub - > parent - > hookstate ) {
@ -2296,7 +2230,7 @@ static int transmit_modify_request(struct mgcp_subchannel *sub)
add_header ( & resp , " R " , ( sub - > rtp & & ( p - > dtmfmode & MGCP_DTMF_INBAND ) ) ? " L/hu(N), L/hf(N) " : " L/hu(N),L/hf(N),D/[0-9#*](N) " ) ;
break ;
}
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_MDCX ;
resp . trid = oseq ;
return send_request ( p , sub , & resp , oseq ) ; /* SC */
@ -2307,10 +2241,10 @@ static int transmit_audit_endpoint(struct mgcp_endpoint *p)
{
struct mgcp_request resp ;
reqprep ( & resp , p , " AUEP " ) ;
/* SC: removed unknown param VS */
/* removed unknown param VS */
/*add_header(&resp, "F", "A,R,D,S,X,N,I,T,O,ES,E,MD,M");*/
add_header ( & resp , " F " , " A " ) ;
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_AUEP ;
resp . trid = oseq ;
return send_request ( p , NULL , & resp , oseq ) ; /* SC */
@ -2326,15 +2260,15 @@ static int transmit_connection_del(struct mgcp_subchannel *sub)
sub - > cxident , p - > name , p - > parent - > name , sub - > id , mgcp_cxmodes [ sub - > cxmode ] , sub - > callid ) ;
}
reqprep ( & resp , p , " DLCX " ) ;
/* SC: check if call id is avail */
/* check if call id is avail */
if ( sub - > callid [ 0 ] )
add_header ( & resp , " C " , sub - > callid ) ;
/* SC: X header should not be sent. kept for compatibility */
/* X header should not be sent. kept for compatibility */
add_header ( & resp , " X " , sub - > txident ) ;
/* SC: check if cxident is avail */
/* check if cxident is avail */
if ( sub - > cxident [ 0 ] )
add_header ( & resp , " I " , sub - > cxident ) ;
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_DLCX ;
resp . trid = oseq ;
return send_request ( p , sub , & resp , oseq ) ; /* SC */
@ -2349,13 +2283,13 @@ static int transmit_connection_del_w_params(struct mgcp_endpoint *p, char *calli
cxident ? cxident : " " , p - > name , p - > parent - > name , callid ? callid : " " ) ;
}
reqprep ( & resp , p , " DLCX " ) ;
/* SC: check if call id is avail */
/* check if call id is avail */
if ( callid & & * callid )
add_header ( & resp , " C " , callid ) ;
/* SC: check if cxident is avail */
/* check if cxident is avail */
if ( cxident & & * cxident )
add_header ( & resp , " I " , cxident ) ;
/* SC: fill in new fields */
/* fill in new fields */
resp . cmd = MGCP_CMD_DLCX ;
resp . trid = oseq ;
return send_request ( p , p - > sub , & resp , oseq ) ;
@ -2427,7 +2361,7 @@ static struct mgcp_request *find_command(struct mgcp_endpoint *p, struct mgcp_su
return req ;
}
/* SC: modified for new transport mechanism */
/* modified for new transport mechanism */
static void handle_response ( struct mgcp_endpoint * p , struct mgcp_subchannel * sub ,
int result , unsigned int ident , struct mgcp_request * resp )
{
@ -2497,7 +2431,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
if ( req - > cmd = = MGCP_CMD_CRCX ) {
if ( ( c = get_header ( resp , " I " ) ) ) {
if ( ! ast_strlen_zero ( c ) & & sub ) {
/* SC: if we are hanging up do not process this conn. */
/* if we are hanging up do not process this conn. */
if ( sub - > owner ) {
if ( ! ast_strlen_zero ( sub - > cxident ) ) {
if ( strcasecmp ( c , sub - > cxident ) ) {
@ -2509,7 +2443,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
transmit_modify_with_sdp ( sub , NULL , 0 ) ;
}
} else {
/* XXX SC: delete this one
/* XXX delete this one
callid and conn id may already be lost .
so the following del conn may have a side effect of
cleaning up the next subchannel */
@ -2520,7 +2454,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
}
if ( req - > cmd = = MGCP_CMD_AUEP ) {
/* SC: check stale connection ids */
/* check stale connection ids */
if ( ( c = get_header ( resp , " I " ) ) ) {
char * v , * n ;
int len ;
@ -2548,16 +2482,16 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
if ( ! ast_strlen_zero ( c ) ) {
if ( strstr ( c , " hu " ) ) {
if ( p - > hookstate ! = MGCP_ONHOOK ) {
/* SC: XXX cleanup if we think we are offhook XXX */
/* XXX cleanup if we think we are offhook XXX */
if ( ( p - > sub - > owner | | p - > sub - > next - > owner ) & &
p - > hookstate = = MGCP_OFFHOOK )
mgcp_queue_hangup ( sub ) ;
p - > hookstate = MGCP_ONHOOK ;
/* SC: update the requested events according to the new hookstate */
/* update the requested events according to the new hookstate */
transmit_notify_request ( p - > sub , " " ) ;
/* SC: verbose level check */
/* verbose level check */
if ( option_verbose > 2 ) {
ast_verbose ( VERBOSE_PREFIX_3 " Setting hookstate of %s@%s to ONHOOK \n " , p - > name , gw - > name ) ;
}
@ -2566,10 +2500,10 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
if ( p - > hookstate ! = MGCP_OFFHOOK ) {
p - > hookstate = MGCP_OFFHOOK ;
/* SC: update the requested events according to the new hookstate */
/* update the requested events according to the new hookstate */
transmit_notify_request ( p - > sub , " " ) ;
/* SC: verbose level check */
/* verbose level check */
if ( option_verbose > 2 ) {
ast_verbose ( VERBOSE_PREFIX_3 " Setting hookstate of %s@%s to OFFHOOK \n " , p - > name , gw - > name ) ;
}
@ -2580,7 +2514,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
}
if ( resp & & resp - > lines ) {
/* SC: do not process sdp if we are hanging up. this may be a late response */
/* do not process sdp if we are hanging up. this may be a late response */
if ( sub & & sub - > owner ) {
if ( ! sub - > rtp )
start_rtp ( sub ) ;
@ -2596,7 +2530,7 @@ static void handle_response(struct mgcp_endpoint *p, struct mgcp_subchannel *sub
static void start_rtp ( struct mgcp_subchannel * sub )
{
ast_mutex_lock ( & sub - > lock ) ;
/* SC: check again to be on the safe side */
/* check again to be on the safe side */
if ( sub - > rtp ) {
ast_rtp_destroy ( sub - > rtp ) ;
sub - > rtp = NULL ;
@ -2888,7 +2822,7 @@ static int attempt_transfer(struct mgcp_endpoint *p)
/* The three-way person we're about to transfer to could still be in MOH, so
stop if now if appropriate */
if ( ast_bridged_channel ( p - > sub - > next - > owner ) )
ast_ moh_stop( ast_bridged_channe l( p - > sub - > next - > owner ) ) ;
ast_ queue_contro l( p - > sub - > next - > owner , AST_CONTROL_UNHOLD ) ;
if ( p - > sub - > owner - > _state = = AST_STATE_RINGING ) {
ast_indicate ( ast_bridged_channel ( p - > sub - > next - > owner ) , AST_CONTROL_RINGING ) ;
}
@ -2903,7 +2837,7 @@ static int attempt_transfer(struct mgcp_endpoint *p)
if ( p - > sub - > owner - > _state = = AST_STATE_RINGING ) {
ast_indicate ( ast_bridged_channel ( p - > sub - > next - > owner ) , AST_CONTROL_RINGING ) ;
}
ast_ moh_stop( ast_bridged_channe l( p - > sub - > next - > owner ) ) ;
ast_ queue_contro l( p - > sub - > next - > owner , AST_CONTROL_UNHOLD ) ;
if ( ast_channel_masquerade ( p - > sub - > owner , ast_bridged_channel ( p - > sub - > next - > owner ) ) ) {
ast_log ( LOG_WARNING , " Unable to masquerade %s as %s \n " ,
ast_bridged_channel ( p - > sub - > next - > owner ) - > name , p - > sub - > owner - > name ) ;
@ -2942,9 +2876,8 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
if ( sub - > outgoing ) {
/* Answered */
if ( sub - > owner ) {
if ( ast_bridged_channel ( sub - > owner ) ) {
ast_moh_stop ( ast_bridged_channel ( sub - > owner ) ) ;
}
if ( ast_bridged_channel ( sub - > owner ) )
ast_queue_control ( sub - > owner , AST_CONTROL_UNHOLD ) ;
sub - > cxmode = MGCP_CX_SENDRECV ;
if ( ! sub - > rtp ) {
start_rtp ( sub ) ;
@ -3000,9 +2933,8 @@ static void handle_hd_hf(struct mgcp_subchannel *sub, char *ev)
ast_log ( LOG_WARNING , " On hook, but already have owner on %s@%s \n " , p - > name , p - > parent - > name ) ;
ast_log ( LOG_WARNING , " If we're onhook why are we here trying to handle a hd or hf? " ) ;
}
if ( ast_bridged_channel ( sub - > owner ) ) {
ast_moh_stop ( ast_bridged_channel ( sub - > owner ) ) ;
}
if ( ast_bridged_channel ( sub - > owner ) )
ast_queue_control ( sub - > owner , AST_CONTROL_UNHOLD ) ;
sub - > cxmode = MGCP_CX_SENDRECV ;
if ( ! sub - > rtp ) {
start_rtp ( sub ) ;
@ -3042,7 +2974,7 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
if ( option_verbose > 2 & & ( strcmp ( p - > name , p - > parent - > wcardep ) ! = 0 ) ) {
ast_verbose ( VERBOSE_PREFIX_3 " Resetting interface %s@%s \n " , p - > name , p - > parent - > name ) ;
}
/* JS: For RSIP on wildcard we reset all endpoints */
/* For RSIP on wildcard we reset all endpoints */
if ( ! strcmp ( p - > name , p - > parent - > wcardep ) ) {
/* Reset all endpoints */
struct mgcp_endpoint * tmp_ep ;
@ -3072,10 +3004,10 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
mgcp_queue_hangup ( sub ) ;
}
transmit_response ( sub , " 200 " , req , " OK " ) ;
/* JS: We dont send NTFY or AUEP to wildcard ep */
/* We dont send NTFY or AUEP to wildcard ep */
if ( strcmp ( p - > name , p - > parent - > wcardep ) ! = 0 ) {
transmit_notify_request ( sub , " " ) ;
/* SC: Audit endpoint.
/* Audit endpoint.
Idea is to prevent lost lines due to race conditions
*/
transmit_audit_endpoint ( p ) ;
@ -3124,9 +3056,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
ast_verbose ( VERBOSE_PREFIX_3 " MGCP Muting %d on %s@%s \n " , sub - > id , p - > name , p - > parent - > name ) ;
}
transmit_modify_request ( sub ) ;
if ( sub - > owner & & ast_bridged_channel ( sub - > owner ) ) {
ast_moh_start ( ast_bridged_channel ( sub - > owner ) , NULL ) ;
}
if ( sub - > owner & & ast_bridged_channel ( sub - > owner ) )
ast_queue_control ( sub - > owner , AST_CONTROL_HOLD ) ;
sub - > next - > cxmode = MGCP_CX_RECVONLY ;
handle_hd_hf ( sub - > next , ev ) ;
} else if ( sub - > owner & & sub - > next - > owner ) {
@ -3139,8 +3070,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
}
sub - > cxmode = MGCP_CX_CONF ;
sub - > next - > cxmode = MGCP_CX_CONF ;
if ( ast_bridged_channel ( sub - > next - > owner ) )
ast_ moh_stop( ast_bridged_channel ( sub - > next - > owner ) ) ;
if ( ast_bridged_channel ( sub - > next - > owner ) )
ast_ queue_control( sub - > next - > owner , AST_CONTROL_UNHOLD ) ;
transmit_modify_request ( sub ) ;
transmit_modify_request ( sub - > next ) ;
} else {
@ -3156,22 +3087,13 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
ast_verbose ( VERBOSE_PREFIX_3 " MGCP Muting %d on %s@%s \n " , sub - > id , p - > name , p - > parent - > name ) ;
}
transmit_modify_request ( sub ) ;
if ( ast_bridged_channel ( sub - > owner ) )
ast_ moh_start( ast_bridged_channel ( sub - > owner ) , NULL ) ;
if ( ast_bridged_channel ( sub - > owner ) )
ast_ queue_control( sub - > owner , AST_CONTROL_HOLD ) ;
if ( ast_bridged_channel ( sub - > next - > owner ) )
ast_ moh_stop( ast_bridged_channel ( sub - > next - > owner ) ) ;
ast_ queue_control( sub - > next - > owner , AST_CONTROL_HOLD ) ;
handle_hd_hf ( sub - > next , ev ) ;
#if 0
if ( sub - > next - > owner & & ( sub - > next - > owner - > _state ! = AST_STATE_UP ) ) {
handle_hd_hf ( sub - > next , ev ) ;
} else {
ast_verbose ( VERBOSE_PREFIX_3 " MGCP Unmuting %d on %s@%s \n " , sub - > next - > id , p - > name , p - > parent - > name ) ;
sub - > next - > cxmode = MGCP_CX_SENDRECV ;
transmit_modify_request ( sub - > next ) ;
}
# endif
}
} else {
/* We've most likely lost one of our calls find an active call and bring it up */
@ -3184,9 +3106,8 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
/* XXX - What do we do now? */
return - 1 ;
}
if ( ast_bridged_channel ( p - > sub - > owner ) ) {
ast_moh_stop ( ast_bridged_channel ( p - > sub - > owner ) ) ;
}
if ( ast_bridged_channel ( p - > sub - > owner ) )
ast_queue_control ( p - > sub - > owner , AST_CONTROL_UNHOLD ) ;
p - > sub - > cxmode = MGCP_CX_SENDRECV ;
transmit_modify_request ( p - > sub ) ;
}
@ -3194,12 +3115,11 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
ast_log ( LOG_WARNING , " Callwaiting, call transfer or threeway calling not enabled on endpoint %s@%s \n " ,
p - > name , p - > parent - > name ) ;
}
/*ast_moh_stop(sub->owner->bridge);*/
} else if ( ! strcasecmp ( ev , " hu " ) ) {
p - > hookstate = MGCP_ONHOOK ;
sub - > cxmode = MGCP_CX_RECVONLY ;
ast_log ( LOG_DEBUG , " MGCP %s@%s Went on hook \n " , p - > name , p - > parent - > name ) ;
/* JS: Do we need to send MDCX before a DLCX ?
/* Do we need to send MDCX before a DLCX ?
if ( sub - > rtp ) {
transmit_modify_request ( sub ) ;
}
@ -3227,7 +3147,7 @@ static int handle_request(struct mgcp_subchannel *sub, struct mgcp_request *req,
sub - > alreadygone = 1 ;
mgcp_queue_hangup ( sub ) ;
} else {
/* SC: verbose level check */
/* verbose level check */
if ( option_verbose > 2 ) {
ast_verbose ( VERBOSE_PREFIX_3 " MGCP handle_request(%s@%s-%d) ast_channel already destroyed, resending DLCX. \n " ,
p - > name , p - > parent - > name , sub - > id ) ;
@ -3486,7 +3406,7 @@ static void *do_monitor(void *data)
pthread_testcancel ( ) ;
/* Wait for sched or io */
res = ast_sched_wait ( sched ) ;
/* SC: copied from chan_sip.c */
/* copied from chan_sip.c */
if ( ( res < 0 ) | | ( res > 1000 ) )
res = 1000 ;
res = ast_io_wait ( io , res ) ;
@ -3582,7 +3502,7 @@ static struct ast_channel *mgcp_request(const char *type, int format, void *data
return tmpc ;
}
/* SC: modified for reload support */
/* modified for reload support */
/*! \brief build_gateway: parse mgcp.conf and create gateway/endpoint structures */
static struct mgcp_gateway * build_gateway ( char * cat , struct ast_variable * v )
{
@ -3595,7 +3515,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
int ep_reload = 0 ;
canreinvite = CANREINVITE ;
/* SC: locate existing gateway */
/* locate existing gateway */
gw = gateways ;
while ( gw ) {
if ( ! strcasecmp ( cat , gw - > name ) ) {
@ -3617,7 +3537,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
gw - > retransid = - 1 ; /* SC */
ast_mutex_init ( & gw - > msgs_lock ) ;
ast_copy_string ( gw - > name , cat , sizeof ( gw - > name ) ) ;
/* SC: check if the name is numeric ip */
/* check if the name is numeric ip */
if ( ( strchr ( gw - > name , ' . ' ) ) & & inet_addr ( gw - > name ) ! = INADDR_NONE )
gw - > isnamedottedip = 1 ;
}
@ -3721,7 +3641,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
} else if ( ! strcasecmp ( v - > name , " threewaycalling " ) ) {
threewaycalling = ast_true ( v - > value ) ;
} else if ( ! strcasecmp ( v - > name , " wcardep " ) ) {
/* SC: locate existing endpoint */
/* locate existing endpoint */
e = gw - > endpoints ;
while ( e ) {
if ( ! strcasecmp ( v - > value , e - > name ) ) {
@ -3822,7 +3742,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
} else if ( ! strcasecmp ( v - > name , " trunk " ) | |
! strcasecmp ( v - > name , " line " ) ) {
/* SC: locate existing endpoint */
/* locate existing endpoint */
e = gw - > endpoints ;
while ( e ) {
if ( ! strcasecmp ( v - > value , e - > name ) ) {
@ -3860,7 +3780,7 @@ static struct mgcp_gateway *build_gateway(char *cat, struct ast_variable *v)
ast_verbose ( VERBOSE_PREFIX_3 " Setting mailbox '%s' on %s@%s \n " , mailbox , gw - > name , e - > name ) ;
}
if ( ! ep_reload ) {
/* XXX SC: potential issue due to reload */
/* XXX potential issue due to reload */
e - > msgstate = - 1 ;
e - > parent = gw ;
}
@ -4204,7 +4124,7 @@ static int reload_config(void)
v = v - > next ;
}
/* SC: mark existing entries for deletion */
/* mark existing entries for deletion */
ast_mutex_lock ( & gatelock ) ;
g = gateways ;
while ( g ) {
@ -4241,7 +4161,7 @@ static int reload_config(void)
cat = ast_category_browse ( cfg , cat ) ;
}
/* SC: prune deleted entries etc. */
/* prune deleted entries etc. */
prune_gateways ( ) ;
if ( ntohl ( bindaddr . sin_addr . s_addr ) ) {
@ -4289,7 +4209,7 @@ static int reload_config(void)
ast_mutex_unlock ( & netlock ) ;
ast_config_destroy ( cfg ) ;
/* SC: send audit only to the new endpoints */
/* send audit only to the new endpoints */
g = gateways ;
while ( g ) {
e = g - > endpoints ;
@ -4403,15 +4323,10 @@ static int unload_module(void *mod)
}
if ( ! ast_mutex_lock ( & gatelock ) ) {
g = gateways ;
while ( g ) {
for ( g = gateways ; g ; g = g - > next ) {
g - > delme = 1 ;
e = g - > endpoints ;
while ( e ) {
for ( e = g - > endpoints ; e ; e = e - > next )
e - > delme = 1 ;
e = e - > next ;
}
g = g - > next ;
}
prune_gateways ( ) ;