2007-07-15 10:03:09 +00:00
/*****************************************************************************\
* * * *
2007-07-18 09:44:25 +00:00
* * Linux Call Router * *
2007-07-15 10:03:09 +00:00
* * * *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * Copyright : Andreas Eversberg * *
* * * *
* * Asterisk socket client * *
* * * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-07-26 12:23:56 +00:00
/*
2008-04-28 17:29:06 +00:00
Registering to LCR :
2007-07-26 12:23:56 +00:00
2008-04-28 17:29:06 +00:00
To connect , open an LCR socket and send a MESSAGE_HELLO to socket with
2007-07-26 12:23:56 +00:00
the application name . This name is unique an can be used for routing calls .
2008-04-28 17:29:06 +00:00
Now the channel driver is linked to LCR and can receive and make calls .
2007-07-26 12:23:56 +00:00
2008-04-28 17:29:06 +00:00
Call is initiated by LCR :
2007-07-26 12:23:56 +00:00
2008-04-28 17:29:06 +00:00
If a call is received from LCR , a MESSAGE_NEWREF is received first .
A new chan_call instance is created . The call reference ( ref ) is given by
MESSAGE_NEWREF . The state is CHAN_LCR_STATE_IN_PREPARE .
After receiving MESSAGE_SETUP from LCR , the ast_channel instance is created
using ast_channel_alloc ( 1 ) . The setup information is given to asterisk .
The new Asterisk instance pointer ( ast ) is stored to chan_call structure .
The state changes to CHAN_LCR_STATE_IN_SETUP .
Call is initiated by Asterisk :
2008-06-06 13:18:59 +00:00
If a call is requested from Asterisk , a new chan_call instance is created .
2008-04-28 17:29:06 +00:00
The new Asterisk instance pointer ( ast ) is stored to chan_call structure .
The current call ref is set to 0 , the state is CHAN_LCR_STATE_OUT_PREPARE .
2008-06-06 13:18:59 +00:00
If the call is received ( lcr_call ) A MESSASGE_NEWREF is sent to LCR requesting
a new call reference ( ref ) .
2008-04-28 17:29:06 +00:00
Further dialing information is queued .
After the new callref is received by special MESSAGE_NEWREF reply , new ref
is stored in the chan_call structure .
The setup information is sent to LCR using MESSAGE_SETUP .
The state changes to CHAN_LCR_STATE_OUT_SETUP .
Call is in process :
During call process , messages are received and sent .
The state changes accordingly .
Any message is allowed to be sent to LCR at any time except MESSAGE_RELEASE .
If a MESSAGE_OVERLAP is received , further dialing is required .
Queued dialing information , if any , is sent to LCR using MESSAGE_DIALING .
In this case , the state changes to CHAN_LCR_STATE_OUT_DIALING .
Call is released by LCR :
A MESSAGE_RELEASE is received with the call reference ( ref ) to be released .
The current ref is set to 0 , to indicate released reference .
The state changes to CHAN_LCR_STATE_RELEASE .
ast_queue_hangup ( ) is called , if asterisk instance ( ast ) exists , if not ,
the chan_call instance is destroyed .
After lcr_hangup ( ) is called - back by Asterisk , the chan_call instance
is destroyed , because the current ref is set to 0 and the state equals
CHAN_LCR_STATE_RELEASE .
If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE , see the proceedure
" Call is released by Asterisk " .
Call is released by Asterisk :
lcr_hangup ( ) is called - back by Asterisk . If the call reference ( ref ) is set ,
a MESSAGE_RELEASE is sent to LCR and the chan_call instance is destroyed .
If the ref is 0 and the state is not CHAN_LCR_STATE_RELEASE , the new state is
set to CHAN_LCR_STATE_RELEASE .
Later , if the MESSAGE_NEWREF reply is received , a MESSAGE_RELEASE is sent to
LCR and the chan_call instance is destroyed .
If the ref is 0 and the state is CHAN_LCR_STATE_RELEASE , see the proceedure
" Call is released by LCR " .
2007-08-12 08:16:19 +00:00
2007-07-26 12:23:56 +00:00
*/
2007-07-15 10:03:09 +00:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <stdarg.h>
# include <errno.h>
# include <sys/types.h>
# include <time.h>
2008-06-01 16:52:10 +00:00
//#include <signal.h>
2007-07-15 10:03:09 +00:00
# include <unistd.h>
# include <fcntl.h>
# include <sys/ioctl.h>
# include <sys/socket.h>
# include <sys/un.h>
2008-04-26 09:18:27 +00:00
# include <semaphore.h>
# include <asterisk/module.h>
# include <asterisk/channel.h>
# include <asterisk/config.h>
# include <asterisk/logger.h>
# include <asterisk/pbx.h>
# include <asterisk/options.h>
# include <asterisk/io.h>
# include <asterisk/frame.h>
# include <asterisk/translate.h>
# include <asterisk/cli.h>
# include <asterisk/musiconhold.h>
# include <asterisk/dsp.h>
# include <asterisk/translate.h>
# include <asterisk/file.h>
# include <asterisk/callerid.h>
# include <asterisk/indications.h>
# include <asterisk/app.h>
# include <asterisk/features.h>
# include <asterisk/sched.h>
2008-05-01 09:56:14 +00:00
# include "extension.h"
# include "message.h"
2008-06-01 16:52:10 +00:00
# include "callerid.h"
2008-05-01 09:56:14 +00:00
# include "lcrsocket.h"
# include "cause.h"
# include "bchannel.h"
2008-06-06 13:18:59 +00:00
# include "options.h"
2008-05-01 09:56:14 +00:00
# include "chan_lcr.h"
2008-04-28 17:29:06 +00:00
CHAN_LCR_STATE // state description structure
2008-06-01 16:52:10 +00:00
MESSAGES // message text
2008-04-28 17:29:06 +00:00
2008-06-01 16:52:10 +00:00
unsigned char flip_bits [ 256 ] ;
2008-05-18 17:04:35 +00:00
2008-04-26 09:18:27 +00:00
int lcr_debug = 1 ;
int mISDN_created = 1 ;
2008-05-01 09:56:14 +00:00
char lcr_type [ ] = " lcr " ;
2008-04-26 10:25:01 +00:00
2008-04-29 07:38:49 +00:00
pthread_t chan_tid ;
2008-05-18 17:04:35 +00:00
ast_mutex_t chan_lock ; /* global lock */
ast_mutex_t log_lock ; /* logging log */
2008-04-29 07:38:49 +00:00
int quit ;
2008-04-26 09:18:27 +00:00
2008-05-01 09:56:14 +00:00
int glob_channel = 0 ;
2008-01-21 08:34:38 +00:00
int lcr_sock = - 1 ;
2007-07-15 10:03:09 +00:00
struct admin_list {
struct admin_list * next ;
2008-06-01 16:52:10 +00:00
struct admin_message msg ;
2007-07-15 10:03:09 +00:00
} * admin_first = NULL ;
2008-05-01 09:56:14 +00:00
static struct ast_channel_tech lcr_tech ;
2008-05-18 17:04:35 +00:00
/*
* logging
*/
2008-06-01 16:52:10 +00:00
void chan_lcr_log ( int type , const char * file , int line , const char * function , struct chan_call * call , struct ast_channel * ast , const char * fmt , . . . )
2008-05-18 17:04:35 +00:00
{
char buffer [ 1024 ] ;
char call_text [ 128 ] = " NULL " ;
char ast_text [ 128 ] = " NULL " ;
va_list args ;
ast_mutex_lock ( & log_lock ) ;
va_start ( args , fmt ) ;
vsnprintf ( buffer , sizeof ( buffer ) - 1 , fmt , args ) ;
buffer [ sizeof ( buffer ) - 1 ] = 0 ;
va_end ( args ) ;
2008-06-06 13:18:59 +00:00
if ( call )
2008-05-18 17:04:35 +00:00
sprintf ( call_text , " %ld " , call - > ref ) ;
if ( ast )
strncpy ( ast_text , ast - > name , sizeof ( ast_text ) - 1 ) ;
ast_text [ sizeof ( ast_text ) - 1 ] = ' \0 ' ;
2008-06-01 16:52:10 +00:00
ast_log ( type , file , line , function , " [call=%s ast=%s] %s " , call_text , ast_text , buffer ) ;
2008-05-18 17:04:35 +00:00
ast_mutex_unlock ( & log_lock ) ;
}
2007-07-15 10:03:09 +00:00
/*
2007-08-12 09:16:45 +00:00
* channel and call instances
*/
struct chan_call * call_first ;
struct chan_call * find_call_ref ( unsigned long ref )
{
struct chan_call * call = call_first ;
while ( call )
{
if ( call - > ref = = ref )
break ;
call = call - > next ;
}
return ( call ) ;
}
2008-05-01 09:56:14 +00:00
#if 0
2008-05-01 18:07:02 +00:00
struct chan_call * find_call_ast ( struct ast_channel * ast )
{
struct chan_call * call = call_first ;
while ( call )
{
if ( call - > ast = = ast )
break ;
call = call - > next ;
}
return ( call ) ;
}
2008-01-19 17:10:46 +00:00
struct chan_call * find_call_handle ( unsigned long handle )
2007-08-12 09:16:45 +00:00
{
struct chan_call * call = call_first ;
while ( call )
{
2008-01-19 17:10:46 +00:00
if ( call - > bchannel_handle = = handle )
2007-08-12 09:16:45 +00:00
break ;
call = call - > next ;
}
return ( call ) ;
}
2008-05-01 09:56:14 +00:00
# endif
2007-08-12 09:16:45 +00:00
void free_call ( struct chan_call * call )
{
struct chan_call * * temp = & call_first ;
while ( * temp )
{
if ( * temp = = call )
{
* temp = ( * temp ) - > next ;
2008-06-01 16:52:10 +00:00
if ( call - > pipe [ 0 ] > - 1 )
2008-05-18 07:23:10 +00:00
close ( call - > pipe [ 0 ] ) ;
2008-06-01 16:52:10 +00:00
if ( call - > pipe [ 1 ] > - 1 )
2008-05-18 07:23:10 +00:00
close ( call - > pipe [ 1 ] ) ;
2008-05-01 18:07:02 +00:00
if ( call - > bchannel )
2008-05-01 08:35:20 +00:00
{
2008-05-18 17:04:35 +00:00
if ( call - > bchannel - > call ! = call )
CERROR ( call , NULL , " Linked bchannel structure has no link to us. \n " ) ;
call - > bchannel - > call = NULL ;
2008-05-01 18:07:02 +00:00
}
if ( call - > bridge_call )
{
2008-05-18 17:04:35 +00:00
if ( call - > bridge_call - > bridge_call ! = call )
CERROR ( call , NULL , " Linked call structure has no link to us. \n " ) ;
call - > bridge_call - > bridge_call = NULL ;
2008-05-01 08:35:20 +00:00
}
2008-05-18 17:04:35 +00:00
CDEBUG ( call , NULL , " Call instance freed. \n " ) ;
2007-08-12 09:16:45 +00:00
free ( call ) ;
return ;
}
temp = & ( ( * temp ) - > next ) ;
}
2008-05-18 17:04:35 +00:00
CERROR ( call , NULL , " Call instance not found in list. \n " ) ;
2007-08-12 09:16:45 +00:00
}
2008-05-18 17:04:35 +00:00
struct chan_call * alloc_call ( void )
{
struct chan_call * * callp = & call_first ;
while ( * callp )
callp = & ( ( * callp ) - > next ) ;
2008-06-01 16:52:10 +00:00
* callp = ( struct chan_call * ) calloc ( 1 , sizeof ( struct chan_call ) ) ;
2008-05-18 17:04:35 +00:00
if ( * callp )
memset ( * callp , 0 , sizeof ( struct chan_call ) ) ;
if ( pipe ( ( * callp ) - > pipe ) < 0 ) {
CERROR ( * callp , NULL , " Failed to create pipe. \n " ) ;
free_call ( * callp ) ;
return ( NULL ) ;
}
CDEBUG ( * callp , NULL , " Call instance allocated. \n " ) ;
return ( * callp ) ;
}
2008-05-01 18:07:02 +00:00
unsigned short new_bridge_id ( void )
2008-02-03 12:47:33 +00:00
{
2008-05-01 18:07:02 +00:00
struct chan_call * call ;
2008-02-03 12:47:33 +00:00
unsigned short id = 1 ;
/* search for lowest bridge id that is not in use and not 0 */
while ( id )
{
2008-05-01 18:07:02 +00:00
call = call_first ;
while ( call )
2008-02-03 12:47:33 +00:00
{
2008-05-01 18:07:02 +00:00
if ( call - > bridge_id = = id )
2008-02-03 12:47:33 +00:00
break ;
2008-05-01 18:07:02 +00:00
call = call - > next ;
2008-02-03 12:47:33 +00:00
}
2008-05-01 18:07:02 +00:00
if ( ! call )
2008-02-03 12:47:33 +00:00
break ;
id + + ;
}
2008-05-18 17:04:35 +00:00
CDEBUG ( NULL , NULL , " New bridge ID %d. \n " , id ) ;
2008-02-03 12:47:33 +00:00
return ( id ) ;
}
2007-08-12 09:16:45 +00:00
/*
* enque message to LCR
2007-07-15 10:03:09 +00:00
*/
2007-08-12 08:16:19 +00:00
int send_message ( int message_type , unsigned long ref , union parameter * param )
2007-07-15 10:03:09 +00:00
{
struct admin_list * admin , * * adminp ;
2008-05-18 17:04:35 +00:00
if ( lcr_sock < 0 ) {
CDEBUG ( NULL , NULL , " Ignoring message %d, because socket is closed. \n " , message_type ) ;
return - 1 ;
}
2008-06-01 16:52:10 +00:00
CDEBUG ( NULL , NULL , " Sending %s to socket. \n " , messages_txt [ message_type ] ) ;
2008-05-18 17:04:35 +00:00
2007-07-15 10:03:09 +00:00
adminp = & admin_first ;
while ( * adminp )
adminp = & ( ( * adminp ) - > next ) ;
2008-06-01 16:52:10 +00:00
admin = ( struct admin_list * ) calloc ( 1 , sizeof ( struct admin_list ) ) ;
if ( ! admin ) {
CERROR ( NULL , NULL , " No memory for message to LCR. \n " ) ;
return - 1 ;
}
2007-07-15 10:03:09 +00:00
* adminp = admin ;
2008-06-01 16:52:10 +00:00
admin - > msg . message = ADMIN_MESSAGE ;
admin - > msg . u . msg . type = message_type ;
admin - > msg . u . msg . ref = ref ;
memcpy ( & admin - > msg . u . msg . param , param , sizeof ( union parameter ) ) ;
2007-07-15 10:03:09 +00:00
return ( 0 ) ;
}
2008-05-01 09:56:14 +00:00
/*
* send setup info to LCR
* this function is called , when asterisk call is received and ref is received
*/
static void send_setup_to_lcr ( struct chan_call * call )
{
union parameter newparam ;
2008-05-01 18:07:02 +00:00
struct ast_channel * ast = call - > ast ;
2008-05-01 09:56:14 +00:00
if ( ! call - > ast | | ! call - > ref )
return ;
2008-06-06 13:18:59 +00:00
CDEBUG ( call , call - > ast , " Sending setup to LCR. (interface=%s dialstring=%s) \n " , call - > interface , call - > dialstring ) ;
2008-05-18 17:04:35 +00:00
2008-05-01 09:56:14 +00:00
/* send setup message to LCR */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
2008-06-06 13:18:59 +00:00
newparam . setup . dialinginfo . itype = INFO_ITYPE_ISDN ;
newparam . setup . dialinginfo . ntype = INFO_NTYPE_UNKNOWN ;
strncpy ( newparam . setup . dialinginfo . id , call - > dialstring , sizeof ( newparam . setup . dialinginfo . id ) - 1 ) ;
strncpy ( newparam . setup . dialinginfo . interfaces , call - > interface , sizeof ( newparam . setup . dialinginfo . interfaces ) - 1 ) ;
2008-05-01 09:56:14 +00:00
newparam . setup . callerinfo . itype = INFO_ITYPE_CHAN ;
2008-06-01 16:52:10 +00:00
newparam . setup . callerinfo . ntype = INFO_NTYPE_UNKNOWN ;
2008-05-01 18:07:02 +00:00
if ( ast - > cid . cid_num ) if ( ast - > cid . cid_num [ 0 ] )
strncpy ( newparam . setup . callerinfo . id , ast - > cid . cid_num , sizeof ( newparam . setup . callerinfo . id ) - 1 ) ;
if ( ast - > cid . cid_name ) if ( ast - > cid . cid_name [ 0 ] )
strncpy ( newparam . setup . callerinfo . name , ast - > cid . cid_name , sizeof ( newparam . setup . callerinfo . name ) - 1 ) ;
if ( ast - > cid . cid_rdnis ) if ( ast - > cid . cid_rdnis [ 0 ] )
2008-05-01 09:56:14 +00:00
{
2008-05-01 18:07:02 +00:00
strncpy ( newparam . setup . redirinfo . id , ast - > cid . cid_rdnis , sizeof ( newparam . setup . redirinfo . id ) - 1 ) ;
2008-05-01 09:56:14 +00:00
newparam . setup . redirinfo . itype = INFO_ITYPE_CHAN ;
newparam . setup . redirinfo . ntype = INFO_NTYPE_UNKNOWN ;
}
2008-05-01 18:07:02 +00:00
switch ( ast - > cid . cid_pres & AST_PRES_RESTRICTION )
2008-05-01 09:56:14 +00:00
{
case AST_PRES_ALLOWED :
newparam . setup . callerinfo . present = INFO_PRESENT_ALLOWED ;
break ;
case AST_PRES_RESTRICTED :
newparam . setup . callerinfo . present = INFO_PRESENT_RESTRICTED ;
break ;
case AST_PRES_UNAVAILABLE :
newparam . setup . callerinfo . present = INFO_PRESENT_NOTAVAIL ;
break ;
default :
newparam . setup . callerinfo . present = INFO_PRESENT_NULL ;
}
2008-05-01 18:07:02 +00:00
switch ( ast - > cid . cid_ton )
2008-05-01 09:56:14 +00:00
{
case 4 :
newparam . setup . callerinfo . ntype = INFO_NTYPE_SUBSCRIBER ;
break ;
case 2 :
newparam . setup . callerinfo . ntype = INFO_NTYPE_NATIONAL ;
break ;
case 1 :
newparam . setup . callerinfo . ntype = INFO_NTYPE_INTERNATIONAL ;
break ;
default :
newparam . setup . callerinfo . ntype = INFO_NTYPE_UNKNOWN ;
}
2008-05-01 18:07:02 +00:00
newparam . setup . capainfo . bearer_capa = ast - > transfercapability ;
2008-06-06 13:18:59 +00:00
newparam . setup . capainfo . bearer_info1 = ( options . law = = ' a ' ) ? 3 : 2 ;
2008-05-01 09:56:14 +00:00
newparam . setup . capainfo . bearer_mode = INFO_BMODE_CIRCUIT ;
newparam . setup . capainfo . hlc = INFO_HLC_NONE ;
newparam . setup . capainfo . exthlc = INFO_HLC_NONE ;
send_message ( MESSAGE_SETUP , call - > ref , & newparam ) ;
/* change to outgoing setup state */
call - > state = CHAN_LCR_STATE_OUT_SETUP ;
}
/*
* send dialing info to LCR
* this function is called , when setup acknowledge is received and dialing
* info is available .
*/
static void send_dialque_to_lcr ( struct chan_call * call )
{
union parameter newparam ;
2008-06-01 16:52:10 +00:00
if ( ! call - > ast | | ! call - > ref | | ! call - > dialque [ 0 ] )
2008-05-01 09:56:14 +00:00
return ;
2008-06-01 16:52:10 +00:00
CDEBUG ( call , call - > ast , " Sending dial queue to LCR. (dialing=%s) \n " , call - > dialque ) ;
2008-05-18 17:04:35 +00:00
2008-05-01 09:56:14 +00:00
/* send setup message to LCR */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
strncpy ( newparam . information . id , call - > dialque , sizeof ( newparam . information . id ) - 1 ) ;
call - > dialque [ 0 ] = ' \0 ' ;
send_message ( MESSAGE_INFORMATION , call - > ref , & newparam ) ;
}
2008-05-01 08:35:20 +00:00
/*
* in case of a bridge , the unsupported message can be forwarded directly
* to the remote call .
*/
static void bridge_message_if_bridged ( struct chan_call * call , int message_type , union parameter * param )
{
/* check bridge */
if ( ! call ) return ;
2008-05-01 18:07:02 +00:00
if ( ! call - > bridge_call ) return ;
2008-05-18 17:04:35 +00:00
CDEBUG ( call , NULL , " Sending message due briding. \n " ) ;
2008-05-18 07:23:10 +00:00
send_message ( message_type , call - > bridge_call - > ref , param ) ;
}
2008-06-01 16:52:10 +00:00
/*
* send release message to LCR and import bchannel if exported
*/
static void send_release_and_import ( struct chan_call * call , int cause , int location )
{
union parameter newparam ;
/* importing channel */
2008-06-06 13:18:59 +00:00
if ( call - > bchannel ) {
2008-06-01 16:52:10 +00:00
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . bchannel . type = BCHANNEL_RELEASE ;
newparam . bchannel . handle = call - > bchannel - > handle ;
send_message ( MESSAGE_BCHANNEL , call - > ref , & newparam ) ;
}
/* sending release */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . disconnectinfo . cause = cause ;
newparam . disconnectinfo . location = LOCATION_PRIVATE_LOCAL ;
send_message ( MESSAGE_RELEASE , call - > ref , & newparam ) ;
}
2008-05-18 07:23:10 +00:00
/*
* check if extension matches and start asterisk
* if it can match , proceed
* if not , release
*/
2008-05-18 17:04:35 +00:00
static void lcr_start_pbx ( struct chan_call * call , struct ast_channel * ast , int complete )
2008-05-18 07:23:10 +00:00
{
2008-05-19 17:39:39 +00:00
int cause , ret ;
union parameter newparam ;
2008-05-18 07:23:10 +00:00
2008-06-01 16:52:10 +00:00
CDEBUG ( call , ast , " Try to start pbx. (exten=%s context=%s complete=%s) \n " , ast - > exten , ast - > context , complete ? " yes " : " no " ) ;
2008-05-18 07:23:10 +00:00
if ( complete )
{
/* if not match */
2008-05-18 17:04:35 +00:00
if ( ! ast_canmatch_extension ( ast , ast - > context , ast - > exten , 1 , call - > oad ) )
2008-05-18 07:23:10 +00:00
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Got 'sending complete', but extension '%s' will not match at context '%s' - releasing. \n " , ast - > exten , ast - > context ) ;
2008-05-18 07:23:10 +00:00
cause = 1 ;
goto release ;
2008-05-25 14:12:20 +00:00
}
2008-05-18 17:04:35 +00:00
if ( ! ast_exists_extension ( ast , ast - > context , ast - > exten , 1 , call - > oad ) )
2008-05-18 07:23:10 +00:00
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Got 'sending complete', but extension '%s' would match at context '%s', if more digits would be dialed - releasing. \n " , ast - > exten , ast - > context ) ;
2008-05-18 07:23:10 +00:00
cause = 28 ;
goto release ;
}
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Got 'sending complete', extensions matches. \n " ) ;
2008-05-18 07:23:10 +00:00
/* send setup acknowledge to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
send_message ( MESSAGE_PROCEEDING , call - > ref , & newparam ) ;
/* change state */
call - > state = CHAN_LCR_STATE_IN_PROCEEDING ;
goto start ;
}
2008-05-19 17:39:39 +00:00
if ( ast_canmatch_extension ( ast , ast - > context , ast - > exten , 1 , call - > oad ) )
2008-05-18 07:23:10 +00:00
{
/* send setup acknowledge to lcr */
2008-06-01 16:52:10 +00:00
if ( call - > state ! = CHAN_LCR_STATE_IN_DIALING ) {
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
send_message ( MESSAGE_OVERLAP , call - > ref , & newparam ) ;
}
2008-05-18 07:23:10 +00:00
/* change state */
call - > state = CHAN_LCR_STATE_IN_DIALING ;
/* if match, start pbx */
2008-05-19 17:39:39 +00:00
if ( ast_exists_extension ( ast , ast - > context , ast - > exten , 1 , call - > oad ) ) {
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Extensions matches. \n " ) ;
2008-05-18 07:23:10 +00:00
goto start ;
2008-05-18 17:04:35 +00:00
}
2008-05-18 07:23:10 +00:00
/* if can match */
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Extensions may match, if more digits are dialed. \n " ) ;
2008-05-18 07:23:10 +00:00
return ;
}
/* if not match */
cause = 1 ;
release :
/* release lcr */
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Releasing due to extension missmatch. \n " ) ;
2008-06-01 16:52:10 +00:00
send_release_and_import ( call , cause , LOCATION_PRIVATE_LOCAL ) ;
2008-05-18 07:23:10 +00:00
call - > ref = 0 ;
/* release asterisk */
ast - > hangupcause = call - > cause ;
/* change to release state */
call - > state = CHAN_LCR_STATE_RELEASE ;
2008-05-18 17:04:35 +00:00
ast_hangup ( ast ) ; // call will be destroyed here
2008-05-18 07:23:10 +00:00
return ;
start :
/* send setup to asterisk */
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Starting call to Asterisk due to matching extension. \n " ) ;
2008-05-18 07:23:10 +00:00
ret = ast_pbx_start ( ast ) ;
if ( ret < 0 )
{
cause = ( ret = = - 2 ) ? 34 : 27 ;
goto release ;
}
call - > pbx_started = 1 ;
return ;
2008-05-01 08:35:20 +00:00
}
2008-04-28 17:29:06 +00:00
/*
* incoming setup from LCR
*/
static void lcr_in_setup ( struct chan_call * call , int message_type , union parameter * param )
{
struct ast_channel * ast ;
2008-06-01 16:52:10 +00:00
CDEBUG ( call , NULL , " Incomming setup from LCR. (callerid %s, dialing %s) \n " , param - > setup . callerinfo . id , param - > setup . dialinginfo . id ) ;
2008-05-18 17:04:35 +00:00
2008-04-28 17:29:06 +00:00
/* create asterisk channel instrance */
2008-05-01 09:56:14 +00:00
ast = ast_channel_alloc ( 1 , AST_STATE_RESERVED , NULL , NULL , " " , NULL , " " , 0 , " %s/%d " , lcr_type , + + glob_channel ) ;
2008-05-18 07:23:10 +00:00
if ( ! ast )
2008-04-28 17:29:06 +00:00
{
/* release */
2008-05-18 17:04:35 +00:00
CERROR ( call , NULL , " Failed to create Asterisk channel - releasing. \n " ) ;
2008-06-01 16:52:10 +00:00
send_release_and_import ( call , CAUSE_RESSOURCEUNAVAIL , LOCATION_PRIVATE_LOCAL ) ;
2008-04-28 17:29:06 +00:00
/* remove call */
free_call ( call ) ;
return ;
}
2008-06-01 16:52:10 +00:00
/* link together */
2008-04-28 17:29:06 +00:00
call - > ast = ast ;
2008-05-01 08:35:20 +00:00
ast - > tech_pvt = call ;
ast - > tech = & lcr_tech ;
2008-05-18 07:23:10 +00:00
ast - > fds [ 0 ] = call - > pipe [ 0 ] ;
2008-04-28 17:29:06 +00:00
/* fill setup information */
2008-05-18 07:23:10 +00:00
if ( param - > setup . dialinginfo . id )
strncpy ( ast - > exten , param - > setup . dialinginfo . id , AST_MAX_EXTENSION - 1 ) ;
if ( param - > setup . context [ 0 ] )
2008-05-19 17:39:39 +00:00
strncpy ( ast - > context , param - > setup . context , AST_MAX_CONTEXT - 1 ) ;
2008-06-01 16:52:10 +00:00
else
strncpy ( ast - > context , param - > setup . callerinfo . interface , AST_MAX_CONTEXT - 1 ) ;
2008-05-01 08:35:20 +00:00
if ( param - > setup . callerinfo . id [ 0 ] )
2008-05-01 09:56:14 +00:00
ast - > cid . cid_num = strdup ( param - > setup . callerinfo . id ) ;
2008-05-01 08:35:20 +00:00
if ( param - > setup . callerinfo . name [ 0 ] )
2008-05-01 09:56:14 +00:00
ast - > cid . cid_name = strdup ( param - > setup . callerinfo . name ) ;
2008-05-01 08:35:20 +00:00
if ( param - > setup . redirinfo . id [ 0 ] )
2008-06-06 13:18:59 +00:00
ast - > cid . cid_name = strdup ( numberrize_callerinfo ( param - > setup . callerinfo . id , param - > setup . callerinfo . ntype , options . national , options . international ) ) ;
2008-05-01 08:35:20 +00:00
switch ( param - > setup . callerinfo . present )
{
case INFO_PRESENT_ALLOWED :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_pres = AST_PRES_ALLOWED ;
2008-05-01 08:35:20 +00:00
break ;
case INFO_PRESENT_RESTRICTED :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_pres = AST_PRES_RESTRICTED ;
2008-05-01 08:35:20 +00:00
break ;
default :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_pres = AST_PRES_UNAVAILABLE ;
2008-05-01 08:35:20 +00:00
}
switch ( param - > setup . callerinfo . ntype )
{
case INFO_NTYPE_SUBSCRIBER :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_ton = 4 ;
2008-05-01 08:35:20 +00:00
break ;
case INFO_NTYPE_NATIONAL :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_ton = 2 ;
2008-05-01 08:35:20 +00:00
break ;
case INFO_NTYPE_INTERNATIONAL :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_ton = 1 ;
2008-05-01 08:35:20 +00:00
break ;
default :
2008-05-01 09:56:14 +00:00
ast - > cid . cid_ton = 0 ;
2008-05-01 08:35:20 +00:00
}
2008-05-01 09:56:14 +00:00
ast - > transfercapability = param - > setup . capainfo . bearer_capa ;
2008-06-06 13:18:59 +00:00
strncpy ( call - > oad , numberrize_callerinfo ( param - > setup . callerinfo . id , param - > setup . callerinfo . ntype , options . national , options . international ) , sizeof ( call - > oad ) - 1 ) ;
2008-05-01 08:35:20 +00:00
/* configure channel */
2008-06-06 13:18:59 +00:00
ast - > nativeformats = ( options . law = = ' a ' ) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW ;
ast - > readformat = ast - > rawreadformat = ast - > nativeformats ;
ast - > writeformat = ast - > rawwriteformat = ast - > nativeformats ;
2008-06-01 16:52:10 +00:00
ast - > priority = 1 ;
2008-05-01 08:35:20 +00:00
ast - > hangupcause = 0 ;
/* change state */
call - > state = CHAN_LCR_STATE_IN_SETUP ;
2008-04-28 17:29:06 +00:00
2008-05-19 17:39:39 +00:00
lcr_start_pbx ( call , ast , param - > setup . dialinginfo . sending_complete ) ;
2008-04-28 17:29:06 +00:00
}
/*
* incoming setup acknowledge from LCR
*/
static void lcr_in_overlap ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-01 08:35:20 +00:00
if ( ! call - > ast ) return ;
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Incomming setup acknowledge from LCR. \n " ) ;
2008-04-28 17:29:06 +00:00
/* send pending digits in dialque */
2008-06-01 16:52:10 +00:00
if ( call - > dialque [ 0 ] )
2008-05-01 08:35:20 +00:00
send_dialque_to_lcr ( call ) ;
2008-04-28 17:29:06 +00:00
/* change to overlap state */
call - > state = CHAN_LCR_STATE_OUT_DIALING ;
}
/*
* incoming proceeding from LCR
*/
static void lcr_in_proceeding ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Incomming proceeding from LCR. \n " ) ;
2008-04-28 17:29:06 +00:00
/* change state */
call - > state = CHAN_LCR_STATE_OUT_PROCEEDING ;
/* send event to asterisk */
2008-05-18 17:04:35 +00:00
if ( call - > ast & & call - > pbx_started )
2008-05-01 09:56:14 +00:00
ast_queue_control ( call - > ast , AST_CONTROL_PROCEEDING ) ;
2008-04-28 17:29:06 +00:00
}
/*
* incoming alerting from LCR
*/
static void lcr_in_alerting ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Incomming alerting from LCR. \n " ) ;
2008-04-28 17:29:06 +00:00
/* change state */
call - > state = CHAN_LCR_STATE_OUT_ALERTING ;
/* send event to asterisk */
2008-05-18 17:04:35 +00:00
if ( call - > ast & & call - > pbx_started )
2008-05-01 09:56:14 +00:00
ast_queue_control ( call - > ast , AST_CONTROL_RINGING ) ;
2008-04-28 17:29:06 +00:00
}
/*
* incoming connect from LCR
*/
static void lcr_in_connect ( struct chan_call * call , int message_type , union parameter * param )
{
2008-06-01 16:52:10 +00:00
union parameter newparam ;
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Incomming connect (answer) from LCR. \n " ) ;
2008-04-28 17:29:06 +00:00
/* change state */
call - > state = CHAN_LCR_STATE_CONNECT ;
2008-06-01 16:52:10 +00:00
/* request bchannel */
if ( ! call - > bchannel ) {
CDEBUG ( call , call - > ast , " Requesting B-channel. \n " ) ;
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . bchannel . type = BCHANNEL_REQUEST ;
send_message ( MESSAGE_BCHANNEL , call - > ref , & newparam ) ;
}
2008-04-28 17:29:06 +00:00
/* copy connectinfo */
2008-05-01 09:56:14 +00:00
memcpy ( & call - > connectinfo , & param - > connectinfo , sizeof ( struct connect_info ) ) ;
2008-04-28 17:29:06 +00:00
/* send event to asterisk */
2008-05-18 17:04:35 +00:00
if ( call - > ast & & call - > pbx_started )
2008-05-01 09:56:14 +00:00
ast_queue_control ( call - > ast , AST_CONTROL_ANSWER ) ;
2008-04-28 17:29:06 +00:00
}
/*
* incoming disconnect from LCR
*/
static void lcr_in_disconnect ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-01 18:07:02 +00:00
struct ast_channel * ast = call - > ast ;
2008-05-01 08:35:20 +00:00
2008-05-19 17:39:39 +00:00
CDEBUG ( call , call - > ast , " Incomming disconnect from LCR. (cause=%d) \n " , param - > disconnectinfo . cause ) ;
2008-05-18 17:04:35 +00:00
2008-04-28 17:29:06 +00:00
/* change state */
call - > state = CHAN_LCR_STATE_IN_DISCONNECT ;
2008-05-01 08:35:20 +00:00
/* save cause */
2008-05-01 09:56:14 +00:00
call - > cause = param - > disconnectinfo . cause ;
call - > location = param - > disconnectinfo . location ;
2008-05-01 08:35:20 +00:00
/* if bridge, forward disconnect and return */
2008-05-18 17:04:35 +00:00
# ifdef TODO
feature flag
2008-05-01 18:07:02 +00:00
if ( call - > bridge_call )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Only signal disconnect via bridge. \n " ) ;
2008-05-01 18:07:02 +00:00
bridge_message_if_bridged ( call , message_type , param ) ;
return ;
}
2008-05-18 17:04:35 +00:00
# endif
/* release lcr with same cause */
2008-06-01 16:52:10 +00:00
send_release_and_import ( call , call - > cause , call - > location ) ;
2008-05-01 09:56:14 +00:00
call - > ref = 0 ;
2008-05-01 08:35:20 +00:00
/* change to release state */
call - > state = CHAN_LCR_STATE_RELEASE ;
2008-05-18 17:04:35 +00:00
/* release asterisk */
if ( ast )
{
ast - > hangupcause = call - > cause ;
if ( call - > pbx_started )
ast_queue_hangup ( ast ) ;
else {
ast_hangup ( ast ) ; // call will be destroyed here
}
}
2008-04-28 17:29:06 +00:00
}
/*
* incoming setup acknowledge from LCR
*/
static void lcr_in_release ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-01 18:07:02 +00:00
struct ast_channel * ast = call - > ast ;
2008-06-01 16:52:10 +00:00
CDEBUG ( call , call - > ast , " Incomming release from LCR, releasing ref. (cause=%d) \n " , param - > disconnectinfo . cause ) ;
2008-05-18 17:04:35 +00:00
2008-04-28 17:29:06 +00:00
/* release ref */
2008-05-01 09:56:14 +00:00
call - > ref = 0 ;
2008-04-28 17:29:06 +00:00
/* change to release state */
call - > state = CHAN_LCR_STATE_RELEASE ;
/* copy release info */
2008-05-01 08:35:20 +00:00
if ( ! call - > cause )
2008-05-01 09:56:14 +00:00
{
call - > cause = param - > disconnectinfo . cause ;
call - > location = param - > disconnectinfo . location ;
}
2008-04-28 17:29:06 +00:00
/* if we have an asterisk instance, send hangup, else we are done */
2008-05-01 18:07:02 +00:00
if ( ast )
2008-04-28 17:29:06 +00:00
{
2008-05-01 18:07:02 +00:00
ast - > hangupcause = call - > cause ;
2008-05-18 17:04:35 +00:00
if ( call - > pbx_started )
ast_queue_hangup ( ast ) ;
else {
ast_hangup ( ast ) ; // call will be destroyed here
}
2008-04-28 17:29:06 +00:00
} else
{
free_call ( call ) ;
}
}
/*
* incoming information from LCR
*/
static void lcr_in_information ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-25 14:12:20 +00:00
struct ast_channel * ast = call - > ast ;
2008-05-01 08:35:20 +00:00
struct ast_frame fr ;
char * p ;
2008-06-01 16:52:10 +00:00
CDEBUG ( call , call - > ast , " Incoming information from LCR. (dialing=%s) \n " , param - > information . id ) ;
2008-05-18 17:04:35 +00:00
2008-05-25 14:12:20 +00:00
if ( ! ast ) return ;
2008-05-18 07:23:10 +00:00
/* pbx not started */
if ( ! call - > pbx_started )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Asterisk not started, adding digits to number. \n " ) ;
2008-05-18 07:23:10 +00:00
strncat ( ast - > exten , param - > information . id , AST_MAX_EXTENSION - 1 ) ;
2008-05-19 17:39:39 +00:00
lcr_start_pbx ( call , ast , param - > information . sending_complete ) ;
2008-05-18 07:23:10 +00:00
return ;
}
2008-05-01 08:35:20 +00:00
2008-04-28 17:29:06 +00:00
/* copy digits */
2008-05-01 09:56:14 +00:00
p = param - > information . id ;
2008-05-01 08:35:20 +00:00
if ( call - > state = = CHAN_LCR_STATE_IN_DIALING & & * p )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Asterisk is started, sending DTMF frame. \n " ) ;
2008-05-01 08:35:20 +00:00
while ( * p )
{
/* send digit to asterisk */
memset ( & fr , 0 , sizeof ( fr ) ) ;
fr . frametype = AST_FRAME_DTMF ;
fr . subclass = * p ;
fr . delivery = ast_tv ( 0 , 0 ) ;
ast_queue_frame ( call - > ast , & fr ) ;
p + + ;
}
}
/* use bridge to forware message not supported by asterisk */
2008-05-18 17:04:35 +00:00
if ( call - > state = = CHAN_LCR_STATE_CONNECT ) {
CDEBUG ( call , call - > ast , " Call is connected, briding. \n " ) ;
2008-05-01 08:35:20 +00:00
bridge_message_if_bridged ( call , message_type , param ) ;
2008-05-18 17:04:35 +00:00
}
2008-05-01 08:35:20 +00:00
}
/*
* incoming information from LCR
*/
static void lcr_in_notify ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-19 17:39:39 +00:00
CDEBUG ( call , call - > ast , " Incomming notify from LCR. (notify=%d) \n " , param - > notifyinfo . notify ) ;
2008-05-18 17:04:35 +00:00
2008-05-01 08:35:20 +00:00
if ( ! call - > ast ) return ;
/* use bridge to forware message not supported by asterisk */
bridge_message_if_bridged ( call , message_type , param ) ;
2008-04-28 17:29:06 +00:00
}
/*
* incoming information from LCR
*/
static void lcr_in_facility ( struct chan_call * call , int message_type , union parameter * param )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Incomming facility from LCR. \n " ) ;
2008-05-01 08:35:20 +00:00
if ( ! call - > ast ) return ;
/* use bridge to forware message not supported by asterisk */
bridge_message_if_bridged ( call , message_type , param ) ;
2008-04-28 17:29:06 +00:00
}
2008-06-06 13:18:59 +00:00
/*
* got dtmf from bchannel
*/
void lcr_in_dtmf ( struct chan_call * call , int val )
{
struct ast_channel * ast = call - > ast ;
struct ast_frame fr ;
if ( ! ast )
return ;
if ( ! call - > pbx_started )
return ;
CDEBUG ( call , call - > ast , " Frowarding DTMF digit '%c' to Asterisk. \n " , val ) ;
/* send digit to asterisk */
memset ( & fr , 0 , sizeof ( fr ) ) ;
fr . frametype = AST_FRAME_DTMF ;
fr . subclass = val ;
fr . delivery = ast_tv ( 0 , 0 ) ;
ast_queue_frame ( call - > ast , & fr ) ;
}
2007-08-12 08:16:19 +00:00
/*
* message received from LCR
*/
int receive_message ( int message_type , unsigned long ref , union parameter * param )
{
2008-01-19 17:10:46 +00:00
struct bchannel * bchannel ;
2007-08-12 09:16:45 +00:00
struct chan_call * call ;
2008-06-06 13:18:59 +00:00
union parameter newparam ;
2007-08-12 08:16:19 +00:00
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
/* handle bchannel message*/
if ( message_type = = MESSAGE_BCHANNEL )
{
2007-08-12 09:16:45 +00:00
switch ( param - > bchannel . type )
2007-08-12 08:16:19 +00:00
{
case BCHANNEL_ASSIGN :
2008-05-19 17:39:39 +00:00
CDEBUG ( NULL , NULL , " Received BCHANNEL_ASSIGN message. (handle=%08lx) \n " , param - > bchannel . handle ) ;
2007-08-26 13:23:58 +00:00
if ( ( bchannel = find_bchannel_handle ( param - > bchannel . handle ) ) )
2007-08-12 08:16:19 +00:00
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " bchannel handle %x already assigned. \n " , ( int ) param - > bchannel . handle ) ;
2007-08-12 08:16:19 +00:00
return ( - 1 ) ;
}
2007-08-12 09:16:45 +00:00
/* create bchannel */
2008-01-19 17:10:46 +00:00
bchannel = alloc_bchannel ( param - > bchannel . handle ) ;
if ( ! bchannel )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " alloc bchannel handle %x failed. \n " , ( int ) param - > bchannel . handle ) ;
2008-01-19 17:10:46 +00:00
return ( - 1 ) ;
}
/* configure channel */
bchannel - > b_tx_gain = param - > bchannel . tx_gain ;
bchannel - > b_rx_gain = param - > bchannel . rx_gain ;
strncpy ( bchannel - > b_pipeline , param - > bchannel . pipeline , sizeof ( bchannel - > b_pipeline ) - 1 ) ;
if ( param - > bchannel . crypt_len )
{
bchannel - > b_crypt_len = param - > bchannel . crypt_len ;
bchannel - > b_crypt_type = param - > bchannel . crypt_type ;
memcpy ( bchannel - > b_crypt_key , param - > bchannel . crypt , param - > bchannel . crypt_len ) ;
}
bchannel - > b_txdata = 0 ;
bchannel - > b_dtmf = 1 ;
bchannel - > b_tx_dejitter = 1 ;
2007-08-12 09:16:45 +00:00
/* in case, ref is not set, this bchannel instance must
2007-08-12 08:16:19 +00:00
* be created until it is removed again by LCR */
/* link to call */
2008-06-06 13:18:59 +00:00
call = find_call_ref ( ref ) ;
if ( call )
2007-08-12 08:16:19 +00:00
{
2008-05-01 09:56:14 +00:00
bchannel - > call = call ;
2008-05-01 18:07:02 +00:00
call - > bchannel = bchannel ;
2008-06-06 13:18:59 +00:00
if ( call - > dtmf )
bchannel_dtmf ( bchannel , 1 ) ;
2008-05-19 17:39:39 +00:00
# ifdef TODO
hier muesen alle bchannel - features gesetzt werden ( pipeline . . . ) falls sie vor dem b - kanal verf <EFBFBD> gbar waren
# endif
2008-05-18 17:04:35 +00:00
if ( call - > bridge_id ) {
CDEBUG ( call , call - > ast , " Join bchannel, because call is already bridged. \n " ) ;
2008-05-01 18:07:02 +00:00
bchannel_join ( bchannel , call - > bridge_id ) ;
2008-05-18 17:04:35 +00:00
}
2007-08-12 08:16:19 +00:00
}
2008-01-19 17:10:46 +00:00
if ( bchannel_create ( bchannel ) )
bchannel_activate ( bchannel , 1 ) ;
2007-08-12 08:16:19 +00:00
/* acknowledge */
newparam . bchannel . type = BCHANNEL_ASSIGN_ACK ;
2007-08-26 13:23:58 +00:00
newparam . bchannel . handle = param - > bchannel . handle ;
2007-08-12 08:16:19 +00:00
send_message ( MESSAGE_BCHANNEL , 0 , & newparam ) ;
2008-06-06 13:18:59 +00:00
/* if call has released before bchannel is assigned */
if ( ! call ) {
newparam . bchannel . type = BCHANNEL_RELEASE ;
newparam . bchannel . handle = param - > bchannel . handle ;
send_message ( MESSAGE_BCHANNEL , 0 , & newparam ) ;
}
2007-08-12 08:16:19 +00:00
break ;
case BCHANNEL_REMOVE :
2008-05-18 17:04:35 +00:00
CDEBUG ( NULL , NULL , " Received BCHANNEL_REMOVE message. (handle=%08lx) \n " , param - > bchannel . handle ) ;
2007-08-26 13:23:58 +00:00
if ( ! ( bchannel = find_bchannel_handle ( param - > bchannel . handle ) ) )
2007-08-12 08:16:19 +00:00
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Bchannel handle %x not assigned. \n " , ( int ) param - > bchannel . handle ) ;
2007-08-12 08:16:19 +00:00
return ( - 1 ) ;
}
2008-05-01 09:56:14 +00:00
/* unklink from call and destroy bchannel */
2007-08-12 09:16:45 +00:00
free_bchannel ( bchannel ) ;
2008-01-19 17:10:46 +00:00
2007-08-12 08:16:19 +00:00
/* acknowledge */
newparam . bchannel . type = BCHANNEL_REMOVE_ACK ;
2007-08-26 13:23:58 +00:00
newparam . bchannel . handle = param - > bchannel . handle ;
2007-08-12 08:16:19 +00:00
send_message ( MESSAGE_BCHANNEL , 0 , & newparam ) ;
break ;
default :
2008-05-18 17:04:35 +00:00
CDEBUG ( NULL , NULL , " Received unknown bchannel message %d. \n " , param - > bchannel . type ) ;
2007-08-12 09:16:45 +00:00
}
return ( 0 ) ;
}
/* handle new ref */
if ( message_type = = MESSAGE_NEWREF )
{
if ( param - > direction )
{
/* new ref from lcr */
2008-06-01 16:52:10 +00:00
CDEBUG ( NULL , NULL , " Received new ref by LCR, due to incomming call. (ref=%ld) \n " , ref ) ;
2007-08-12 09:16:45 +00:00
if ( ! ref | | find_call_ref ( ref ) )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Illegal new ref %ld received. \n " , ref ) ;
2007-08-12 09:16:45 +00:00
return ( - 1 ) ;
}
2008-04-28 17:29:06 +00:00
/* allocate new call instance */
2007-08-12 09:16:45 +00:00
call = alloc_call ( ) ;
2008-04-28 17:29:06 +00:00
/* new state */
call - > state = CHAN_LCR_STATE_IN_PREPARE ;
/* set ref */
2007-08-12 09:16:45 +00:00
call - > ref = ref ;
2008-04-28 17:29:06 +00:00
/* wait for setup (or release from asterisk) */
2007-08-12 09:16:45 +00:00
} else
{
/* new ref, as requested from this remote application */
2008-05-18 17:04:35 +00:00
CDEBUG ( NULL , NULL , " Received new ref by LCR, as requested from chan_lcr. (ref=%ld) \n " , ref ) ;
2007-08-12 09:16:45 +00:00
call = find_call_ref ( 0 ) ;
if ( ! call )
{
/* send release, if ref does not exist */
2008-05-18 17:04:35 +00:00
CDEBUG ( NULL , NULL , " No call found, that requests a ref. \n " ) ;
2008-06-01 16:52:10 +00:00
send_release_and_import ( call , CAUSE_NORMAL , LOCATION_PRIVATE_LOCAL ) ;
2007-08-12 09:16:45 +00:00
return ( 0 ) ;
}
2008-04-28 17:29:06 +00:00
/* store new ref */
2007-08-12 09:16:45 +00:00
call - > ref = ref ;
2008-04-28 17:29:06 +00:00
/* send pending setup info */
if ( call - > state = = CHAN_LCR_STATE_OUT_PREPARE )
send_setup_to_lcr ( call ) ;
/* release if asterisk has signed off */
else if ( call - > state = = CHAN_LCR_STATE_RELEASE )
{
/* send release */
2008-05-01 09:56:14 +00:00
if ( call - > cause )
2008-06-01 16:52:10 +00:00
send_release_and_import ( call , call - > cause , call - > location ) ;
else
send_release_and_import ( call , CAUSE_NORMAL , LOCATION_PRIVATE_LOCAL ) ;
2008-04-28 17:29:06 +00:00
/* free call */
free_call ( call ) ;
return ( 0 ) ;
}
2007-08-12 08:16:19 +00:00
}
return ( 0 ) ;
}
2007-08-12 09:16:45 +00:00
/* check ref */
if ( ! ref )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Received message %d without ref. \n " , message_type ) ;
2007-08-12 09:16:45 +00:00
return ( - 1 ) ;
}
call = find_call_ref ( ref ) ;
if ( ! call )
{
/* ignore ref that is not used (anymore) */
2008-05-19 17:39:39 +00:00
CDEBUG ( NULL , NULL , " Message %d from LCR ignored, because no call instance found. \n " , message_type ) ;
2007-08-12 09:16:45 +00:00
return ( 0 ) ;
}
/* handle messages */
2007-08-12 08:16:19 +00:00
switch ( message_type )
2007-08-12 09:16:45 +00:00
{
2008-01-21 08:34:38 +00:00
case MESSAGE_SETUP :
2008-04-28 17:29:06 +00:00
lcr_in_setup ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
case MESSAGE_OVERLAP :
2008-04-28 17:29:06 +00:00
lcr_in_overlap ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
case MESSAGE_PROCEEDING :
2008-04-28 17:29:06 +00:00
lcr_in_proceeding ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
case MESSAGE_ALERTING :
2008-04-28 17:29:06 +00:00
lcr_in_alerting ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
case MESSAGE_CONNECT :
2008-04-28 17:29:06 +00:00
lcr_in_connect ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
case MESSAGE_DISCONNECT :
2008-04-28 17:29:06 +00:00
lcr_in_disconnect ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
2007-08-12 09:16:45 +00:00
case MESSAGE_RELEASE :
2008-04-28 17:29:06 +00:00
lcr_in_release ( call , message_type , param ) ;
break ;
2007-08-12 09:16:45 +00:00
2008-01-21 08:34:38 +00:00
case MESSAGE_INFORMATION :
2008-05-01 18:07:02 +00:00
lcr_in_information ( call , message_type , param ) ;
2007-08-12 09:16:45 +00:00
break ;
2008-01-21 08:34:38 +00:00
2008-05-01 08:35:20 +00:00
case MESSAGE_NOTIFY :
lcr_in_notify ( call , message_type , param ) ;
break ;
2008-01-21 08:34:38 +00:00
case MESSAGE_FACILITY :
2008-05-01 08:35:20 +00:00
lcr_in_facility ( call , message_type , param ) ;
2008-01-21 08:34:38 +00:00
break ;
2008-05-19 17:39:39 +00:00
case MESSAGE_PATTERN : // audio available from LCR
2008-01-21 08:34:38 +00:00
break ;
2008-05-19 17:39:39 +00:00
case MESSAGE_NOPATTERN : // audio not available from LCR
2008-01-21 08:34:38 +00:00
break ;
2008-05-19 17:39:39 +00:00
case MESSAGE_AUDIOPATH : // if remote audio connected or hold
call - > audiopath = param - > audiopath ;
2008-01-21 08:34:38 +00:00
break ;
default :
2008-05-19 17:39:39 +00:00
CDEBUG ( call , call - > ast , " Message %d from LCR unhandled. \n " , message_type ) ;
2008-05-01 09:56:14 +00:00
break ;
2007-08-12 09:16:45 +00:00
}
2007-08-12 08:16:19 +00:00
return ( 0 ) ;
}
2008-05-18 17:04:35 +00:00
/*
* release all calls ( due to broken socket )
*/
static void release_all_calls ( void )
{
struct chan_call * call ;
again :
call = call_first ;
2008-06-01 16:52:10 +00:00
while ( call ) {
2008-05-18 17:04:35 +00:00
/* no ast, so we may directly free call */
if ( ! call - > ast ) {
CDEBUG ( call , NULL , " Freeing call, because no Asterisk channel is linked. \n " ) ;
free_call ( call ) ;
goto again ;
}
/* already in release process */
if ( call - > state = = CHAN_LCR_STATE_RELEASE ) {
call = call - > next ;
continue ;
}
/* release or queue release */
call - > ref = 0 ;
call - > state = CHAN_LCR_STATE_RELEASE ;
2008-06-01 16:52:10 +00:00
if ( ! call - > pbx_started ) {
2008-05-18 17:04:35 +00:00
CDEBUG ( call , call - > ast , " Releasing call, because no Asterisk channel is not started. \n " ) ;
ast_hangup ( call - > ast ) ; // call will be destroyed here
goto again ;
}
CDEBUG ( call , call - > ast , " Queue call release, because Asterisk channel is running. \n " ) ;
ast_queue_hangup ( call - > ast ) ;
call = call - > next ;
}
2008-06-01 16:52:10 +00:00
/* release all bchannels */
while ( bchannel_first )
free_bchannel ( bchannel_first ) ;
2008-05-18 17:04:35 +00:00
}
2007-07-15 10:03:09 +00:00
/* asterisk handler
* warning ! not thread safe
* returns - 1 for socket error , 0 for no work , 1 for work
*/
int handle_socket ( void )
{
int work = 0 ;
int len ;
struct admin_list * admin ;
2008-06-01 16:52:10 +00:00
struct admin_message msg ;
2008-04-26 09:18:27 +00:00
2007-07-15 10:03:09 +00:00
/* read from socket */
2008-06-01 16:52:10 +00:00
len = read ( lcr_sock , & msg , sizeof ( msg ) ) ;
2007-07-15 10:03:09 +00:00
if ( len = = 0 )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket closed. \n " ) ;
2007-07-15 10:03:09 +00:00
return ( - 1 ) ; // socket closed
}
if ( len > 0 )
{
if ( len ! = sizeof ( msg ) )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket short read. (len %d) \n " , len ) ;
2007-07-15 10:03:09 +00:00
return ( - 1 ) ; // socket error
}
if ( msg . message ! = ADMIN_MESSAGE )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket received illegal message %d. \n " , msg . message ) ;
2008-06-01 16:52:10 +00:00
return ( - 1 ) ;
2007-07-15 10:03:09 +00:00
}
2007-08-12 09:16:45 +00:00
receive_message ( msg . u . msg . type , msg . u . msg . ref , & msg . u . msg . param ) ;
2007-07-15 10:03:09 +00:00
work = 1 ;
} else
{
if ( errno ! = EWOULDBLOCK )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket failed (errno %d). \n " , errno ) ;
2007-07-15 10:03:09 +00:00
return ( - 1 ) ;
}
}
/* write to socket */
if ( ! admin_first )
return ( work ) ;
admin = admin_first ;
2008-06-01 16:52:10 +00:00
len = write ( lcr_sock , & admin - > msg , sizeof ( msg ) ) ;
2007-07-15 10:03:09 +00:00
if ( len = = 0 )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket closed. \n " ) ;
2007-07-15 10:03:09 +00:00
return ( - 1 ) ; // socket closed
}
if ( len > 0 )
{
if ( len ! = sizeof ( msg ) )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket short write. (len %d) \n " , len ) ;
2007-07-15 10:03:09 +00:00
return ( - 1 ) ; // socket error
}
/* free head */
admin_first = admin - > next ;
2008-01-19 17:44:26 +00:00
free ( admin ) ;
2007-07-15 10:03:09 +00:00
work = 1 ;
} else
{
if ( errno ! = EWOULDBLOCK )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Socket failed (errno %d). \n " , errno ) ;
2007-07-15 10:03:09 +00:00
return ( - 1 ) ;
}
}
return ( work ) ;
}
/*
2008-05-01 09:56:14 +00:00
* open and close socket and thread
2007-07-15 10:03:09 +00:00
*/
2008-01-21 08:34:38 +00:00
int open_socket ( void )
2007-07-15 10:03:09 +00:00
{
2008-01-21 08:34:38 +00:00
int ret ;
2007-07-15 10:03:09 +00:00
char * socket_name = SOCKET_NAME ;
int conn ;
struct sockaddr_un sock_address ;
unsigned long on = 1 ;
2007-07-26 12:23:56 +00:00
union parameter param ;
2007-07-15 10:03:09 +00:00
/* open socket */
2008-06-01 16:52:10 +00:00
if ( ( lcr_sock = socket ( PF_UNIX , SOCK_STREAM , 0 ) ) < 0 )
2007-07-15 10:03:09 +00:00
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Failed to create socket. \n " ) ;
2008-06-01 16:52:10 +00:00
return ( lcr_sock ) ;
2007-07-15 10:03:09 +00:00
}
/* set socket address and name */
memset ( & sock_address , 0 , sizeof ( sock_address ) ) ;
sock_address . sun_family = PF_UNIX ;
2008-01-19 17:44:26 +00:00
strcpy ( sock_address . sun_path , socket_name ) ;
2007-07-15 10:03:09 +00:00
/* connect socket */
2008-06-01 16:52:10 +00:00
if ( ( conn = connect ( lcr_sock , ( struct sockaddr * ) & sock_address , SUN_LEN ( & sock_address ) ) ) < 0 )
2007-07-15 10:03:09 +00:00
{
2008-06-01 16:52:10 +00:00
close ( lcr_sock ) ;
lcr_sock = - 1 ;
CDEBUG ( NULL , NULL , " Failed to connect to socket '%s'. Is LCR running? \n " , sock_address . sun_path ) ;
2008-01-21 08:34:38 +00:00
return ( conn ) ;
2007-07-15 10:03:09 +00:00
}
/* set non-blocking io */
2008-06-01 16:52:10 +00:00
if ( ( ret = ioctl ( lcr_sock , FIONBIO , ( unsigned char * ) ( & on ) ) ) < 0 )
2007-07-15 10:03:09 +00:00
{
2008-06-01 16:52:10 +00:00
close ( lcr_sock ) ;
lcr_sock = - 1 ;
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Failed to set socket into non-blocking IO. \n " ) ;
2008-01-21 08:34:38 +00:00
return ( ret ) ;
2007-07-15 10:03:09 +00:00
}
/* enque hello message */
2007-07-26 12:23:56 +00:00
memset ( & param , 0 , sizeof ( param ) ) ;
2008-01-19 17:44:26 +00:00
strcpy ( param . hello . application , " asterisk " ) ;
2007-08-12 09:16:45 +00:00
send_message ( MESSAGE_HELLO , 0 , & param ) ;
2007-07-15 10:03:09 +00:00
2008-06-01 16:52:10 +00:00
return ( lcr_sock ) ;
2008-01-21 08:34:38 +00:00
}
2008-06-01 16:52:10 +00:00
void close_socket ( void )
2008-01-21 08:34:38 +00:00
{
2008-06-01 16:52:10 +00:00
struct admin_list * admin , * temp ;
/* flush pending messages */
admin = admin_first ;
while ( admin ) {
temp = admin ;
admin = admin - > next ;
free ( temp ) ;
}
admin_first = NULL ;
2008-01-21 08:34:38 +00:00
/* close socket */
2008-06-01 16:52:10 +00:00
if ( lcr_sock > = 0 )
close ( lcr_sock ) ;
lcr_sock = - 1 ;
}
void sighandler ( int sigset )
{
2008-01-21 08:34:38 +00:00
}
2008-04-29 07:38:49 +00:00
static void * chan_thread ( void * arg )
2008-01-21 08:34:38 +00:00
{
int work ;
2008-05-18 07:23:10 +00:00
int ret ;
2008-05-18 17:04:35 +00:00
union parameter param ;
time_t retry = 0 , now ;
bchannel_pid = getpid ( ) ;
2008-06-01 16:52:10 +00:00
// signal(SIGPIPE, sighandler);
2008-05-18 17:04:35 +00:00
memset ( & param , 0 , sizeof ( union parameter ) ) ;
2008-06-01 16:52:10 +00:00
if ( lcr_sock < 0 )
2008-05-18 17:04:35 +00:00
time ( & retry ) ;
2008-01-21 08:34:38 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-04-29 08:00:44 +00:00
2008-05-18 17:04:35 +00:00
while ( ! quit ) {
2008-01-19 17:10:46 +00:00
work = 0 ;
2008-05-18 17:04:35 +00:00
if ( lcr_sock > 0 ) {
/* handle socket */
ret = handle_socket ( ) ;
if ( ret < 0 ) {
CERROR ( NULL , NULL , " Handling of socket failed - closing for some seconds. \n " ) ;
2008-06-01 16:52:10 +00:00
close_socket ( ) ;
2008-05-18 17:04:35 +00:00
release_all_calls ( ) ;
time ( & retry ) ;
}
if ( ret )
work = 1 ;
} else {
time ( & now ) ;
if ( retry & & now - retry > 5 ) {
2008-06-01 16:52:10 +00:00
CDEBUG ( NULL , NULL , " Retry to open socket. \n " ) ;
2008-05-18 17:04:35 +00:00
retry = 0 ;
2008-06-01 16:52:10 +00:00
if ( open_socket ( ) < 0 ) {
2008-05-18 17:04:35 +00:00
time ( & retry ) ;
}
work = 1 ;
}
}
2008-01-19 17:10:46 +00:00
/* handle mISDN */
ret = bchannel_handle ( ) ;
if ( ret )
work = 1 ;
2008-05-18 17:04:35 +00:00
if ( ! work ) {
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2007-07-15 10:03:09 +00:00
usleep ( 30000 ) ;
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-04-29 06:33:06 +00:00
}
2007-07-15 10:03:09 +00:00
}
2008-05-18 17:04:35 +00:00
2008-06-01 16:52:10 +00:00
close_socket ( ) ;
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Thread exit. \n " ) ;
2008-04-29 08:00:44 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-04-29 08:00:44 +00:00
2008-06-01 16:52:10 +00:00
// signal(SIGPIPE, SIG_DFL);
2008-04-29 07:38:49 +00:00
return NULL ;
2008-01-21 08:34:38 +00:00
}
2008-04-28 17:29:06 +00:00
/*
* new asterisk instance
*/
2008-05-19 17:39:39 +00:00
static
struct ast_channel * lcr_request ( const char * type , int format , void * data , int * cause )
2008-04-28 17:29:06 +00:00
{
2008-06-06 13:18:59 +00:00
char exten [ 256 ] , * dial , * interface , * opt ;
2008-05-01 09:56:14 +00:00
struct ast_channel * ast ;
2008-06-06 13:18:59 +00:00
struct chan_call * call ;
2008-05-01 08:35:20 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-04-29 06:33:06 +00:00
2008-06-06 13:18:59 +00:00
CDEBUG ( NULL , NULL , " Received request from Asterisk. data=%s \n " , ( char * ) data ) ;
2008-05-18 17:04:35 +00:00
/* if socket is closed */
if ( lcr_sock < 0 )
{
CERROR ( NULL , NULL , " Rejecting call from Asterisk, because LCR not running. \n " ) ;
return NULL ;
}
2008-06-02 16:13:45 +00:00
2008-06-06 13:18:59 +00:00
/* create call instance */
call = alloc_call ( ) ;
if ( ! call )
{
/* failed to create instance */
return NULL ;
}
2008-04-28 17:29:06 +00:00
/* create asterisk channel instrance */
2008-05-01 18:07:02 +00:00
ast = ast_channel_alloc ( 1 , AST_STATE_RESERVED , NULL , NULL , " " , NULL , " " , 0 , " %s/%d " , lcr_type , + + glob_channel ) ;
2008-04-28 17:29:06 +00:00
if ( ! ast )
{
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Failed to create Asterisk channel. \n " ) ;
2008-06-06 13:18:59 +00:00
free_call ( call ) ;
2008-04-28 17:29:06 +00:00
/* failed to create instance */
return NULL ;
}
2008-05-01 08:35:20 +00:00
ast - > tech = & lcr_tech ;
2008-06-06 13:18:59 +00:00
ast - > tech_pvt = ( void * ) 1L ; // set pointer or asterisk will not call
2008-05-01 08:35:20 +00:00
/* configure channel */
2008-06-06 13:18:59 +00:00
ast - > nativeformats = ( options . law = = ' a ' ) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW ;
ast - > readformat = ast - > rawreadformat = ast - > nativeformats ;
ast - > writeformat = ast - > rawwriteformat = ast - > nativeformats ;
2008-06-01 16:52:10 +00:00
ast - > priority = 1 ;
2008-05-01 08:35:20 +00:00
ast - > hangupcause = 0 ;
2008-04-29 06:33:06 +00:00
2008-06-06 13:18:59 +00:00
/* link together */
call - > ast = ast ;
ast - > tech_pvt = call ;
ast - > fds [ 0 ] = call - > pipe [ 0 ] ;
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-06-06 13:18:59 +00:00
call - > pbx_started = 0 ;
/* set state */
call - > state = CHAN_LCR_STATE_OUT_PREPARE ;
/*
* Extract interface , dialstring , options from data .
* Formats can be :
* < dialstring >
* < interface > / < dialstring >
* < interface > / < dialstring > / options
*/
strncpy ( exten , ( char * ) data , sizeof ( exten ) - 1 ) ;
exten [ sizeof ( exten ) - 1 ] = ' \0 ' ;
if ( ( dial = strchr ( exten , ' / ' ) ) ) {
* dial + + = ' \0 ' ;
interface = exten ;
if ( ( opt = strchr ( dial , ' / ' ) ) )
* opt + + = ' \0 ' ;
else
opt = " " ;
} else {
dial = exten ;
interface = " " ;
opt = " " ;
}
strncpy ( call - > interface , interface , sizeof ( call - > interface ) - 1 ) ;
strncpy ( call - > dialstring , dial , sizeof ( call - > dialstring ) - 1 ) ;
# warning todo: parse options
2008-05-01 18:07:02 +00:00
return ast ;
2008-04-28 17:29:06 +00:00
}
/*
* call from asterisk
*/
2008-02-03 12:47:33 +00:00
static int lcr_call ( struct ast_channel * ast , char * dest , int timeout )
{
2008-06-02 16:13:45 +00:00
union parameter newparam ;
2008-06-06 13:18:59 +00:00
struct chan_call * call ;
2008-02-03 12:47:33 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
CERROR ( NULL , ast , " Received call from Asterisk, but call instance does not exist. \n " ) ;
2008-05-18 07:23:10 +00:00
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
2008-06-02 16:13:45 +00:00
CDEBUG ( NULL , ast , " Received call from Asterisk. \n " ) ;
2008-02-03 12:47:33 +00:00
2008-06-02 16:13:45 +00:00
/* pbx process is started */
2008-05-18 17:04:35 +00:00
call - > pbx_started = 1 ;
2008-06-02 16:13:45 +00:00
/* send MESSAGE_NEWREF */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . direction = 0 ; /* request from app */
send_message ( MESSAGE_NEWREF , 0 , & newparam ) ;
2008-04-28 17:29:06 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-04-26 09:18:27 +00:00
return 0 ;
}
2008-02-03 12:47:33 +00:00
2008-04-28 17:29:06 +00:00
static int lcr_digit ( struct ast_channel * ast , char digit )
{
2008-05-18 07:23:10 +00:00
struct chan_call * call ;
2008-05-01 08:35:20 +00:00
union parameter newparam ;
2008-04-28 17:29:06 +00:00
char buf [ ] = " x " ;
/* only pass IA5 number space */
if ( digit > 126 | | digit < 32 )
return 0 ;
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-05-18 17:04:35 +00:00
CERROR ( NULL , ast , " Received digit from Asterisk, but no call instance exists. \n " ) ;
2008-05-18 07:23:10 +00:00
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
2008-04-29 06:33:06 +00:00
2008-06-06 13:18:59 +00:00
CDEBUG ( call , ast , " Received digit '%c' from Asterisk. \n " , digit ) ;
2008-05-18 17:04:35 +00:00
2008-04-28 17:29:06 +00:00
/* send information or queue them */
if ( call - > ref & & call - > state = = CHAN_LCR_STATE_OUT_DIALING )
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Sending digit to LCR, because we are in dialing state. \n " ) ;
2008-05-01 08:35:20 +00:00
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
2008-05-01 18:07:02 +00:00
newparam . information . id [ 0 ] = digit ;
newparam . information . id [ 1 ] = ' \0 ' ;
2008-05-01 08:35:20 +00:00
send_message ( MESSAGE_INFORMATION , call - > ref , & newparam ) ;
2008-04-28 17:29:06 +00:00
} else
if ( ! call - > ref
2008-06-06 13:18:59 +00:00
& & ( call - > state = = CHAN_LCR_STATE_OUT_PREPARE | | call - > state = = CHAN_LCR_STATE_OUT_SETUP ) )
2008-04-28 17:29:06 +00:00
{
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Queue digits, because we are in setup/dialing state and have no ref yet. \n " ) ;
2008-04-28 17:29:06 +00:00
* buf = digit ;
2008-05-01 18:07:02 +00:00
strncat ( call - > dialque , buf , strlen ( call - > dialque ) - 1 ) ;
2008-04-28 17:29:06 +00:00
}
2008-04-29 06:33:06 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-04-29 06:33:06 +00:00
return ( 0 ) ;
2008-04-28 17:29:06 +00:00
}
2008-05-01 18:07:02 +00:00
static int lcr_answer ( struct ast_channel * ast )
2008-04-26 09:18:27 +00:00
{
2008-05-01 08:35:20 +00:00
union parameter newparam ;
2008-05-18 07:23:10 +00:00
struct chan_call * call ;
2008-05-01 08:35:20 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-05-18 17:04:35 +00:00
CERROR ( NULL , ast , " Received answer from Asterisk, but no call instance exists. \n " ) ;
2008-05-18 07:23:10 +00:00
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Received answer from Asterisk. \n " ) ;
2008-05-01 18:07:02 +00:00
/* copy connectinfo, if bridged */
if ( call - > bridge_call )
memcpy ( & call - > connectinfo , & call - > bridge_call - > connectinfo , sizeof ( struct connect_info ) ) ;
2008-05-01 08:35:20 +00:00
/* send connect message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
2008-05-01 18:07:02 +00:00
memcpy ( & newparam . connectinfo , & call - > connectinfo , sizeof ( struct connect_info ) ) ;
2008-05-01 08:35:20 +00:00
send_message ( MESSAGE_CONNECT , call - > ref , & newparam ) ;
/* change state */
call - > state = CHAN_LCR_STATE_CONNECT ;
2008-06-01 16:52:10 +00:00
/* request bchannel */
if ( ! call - > bchannel ) {
CDEBUG ( call , ast , " Requesting B-channel. \n " ) ;
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . bchannel . type = BCHANNEL_REQUEST ;
send_message ( MESSAGE_BCHANNEL , call - > ref , & newparam ) ;
}
2008-06-06 13:18:59 +00:00
/* enable keypad */
// memset(&newparam, 0, sizeof(union parameter));
// send_message(MESSAGE_ENABLEKEYPAD, call->ref, &newparam);
call - > dtmf = 1 ;
2008-05-01 08:35:20 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-04-26 09:18:27 +00:00
return 0 ;
}
2008-02-03 12:47:33 +00:00
2008-04-28 17:29:06 +00:00
static int lcr_hangup ( struct ast_channel * ast )
2008-04-26 09:18:27 +00:00
{
2008-05-18 07:23:10 +00:00
struct chan_call * call ;
2008-05-18 17:04:35 +00:00
pthread_t tid = pthread_self ( ) ;
2008-04-29 06:33:06 +00:00
2008-05-19 17:39:39 +00:00
if ( ! pthread_equal ( tid , chan_tid ) )
2008-05-18 17:04:35 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-05-18 17:04:35 +00:00
CERROR ( NULL , ast , " Received hangup from Asterisk, but no call instance exists. \n " ) ;
2008-05-19 17:39:39 +00:00
if ( ! pthread_equal ( tid , chan_tid ) )
2008-05-18 17:04:35 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
return - 1 ;
}
2008-05-19 17:39:39 +00:00
if ( ! pthread_equal ( tid , chan_tid ) )
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Received hangup from Asterisk thread. \n " ) ;
else
CDEBUG ( call , ast , " Received hangup from LCR thread. \n " ) ;
2008-04-28 17:29:06 +00:00
/* disconnect asterisk, maybe not required */
ast - > tech_pvt = NULL ;
2008-05-18 07:23:10 +00:00
ast - > fds [ 0 ] = - 1 ;
2008-04-29 06:33:06 +00:00
if ( call - > ref )
2008-04-28 17:29:06 +00:00
{
/* release */
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Releasing ref and freeing call instance. \n " ) ;
2008-06-01 16:52:10 +00:00
if ( ast - > hangupcause > 0 )
send_release_and_import ( call , ast - > hangupcause , LOCATION_PRIVATE_LOCAL ) ;
else
send_release_and_import ( call , CAUSE_RESSOURCEUNAVAIL , LOCATION_PRIVATE_LOCAL ) ;
2008-04-28 17:29:06 +00:00
/* remove call */
free_call ( call ) ;
2008-05-19 17:39:39 +00:00
if ( ! pthread_equal ( tid , chan_tid ) )
2008-05-18 17:04:35 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-04-29 06:33:06 +00:00
return 0 ;
2008-04-28 17:29:06 +00:00
} else
{
/* ref is not set, due to prepare setup or release */
if ( call - > state = = CHAN_LCR_STATE_RELEASE )
{
/* we get the response to our release */
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Freeing call instance, because we have no ref AND we are requesting no ref. \n " ) ;
2008-04-28 17:29:06 +00:00
free_call ( call ) ;
} else
{
/* during prepare, we change to release state */
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " We must wait until we received our ref, until we can free call instance. \n " ) ;
2008-04-28 17:29:06 +00:00
call - > state = CHAN_LCR_STATE_RELEASE ;
}
}
2008-05-19 17:39:39 +00:00
if ( ! pthread_equal ( tid , chan_tid ) )
2008-05-18 17:04:35 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-04-29 06:33:06 +00:00
return 0 ;
2008-04-28 17:29:06 +00:00
}
2008-02-03 12:47:33 +00:00
2008-05-01 08:35:20 +00:00
static int lcr_write ( struct ast_channel * ast , struct ast_frame * f )
2008-04-26 09:18:27 +00:00
{
2008-05-18 07:23:10 +00:00
struct chan_call * call ;
2008-06-01 16:52:10 +00:00
if ( ! f - > subclass )
CDEBUG ( NULL , ast , " No subclass \n " ) ;
2008-06-06 13:18:59 +00:00
if ( ! ( f - > subclass & ast - > nativeformats ) )
2008-06-01 16:52:10 +00:00
CDEBUG ( NULL , ast , " Unexpected format. \n " ) ;
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-05-18 07:23:10 +00:00
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
2008-06-01 16:52:10 +00:00
if ( call - > bchannel & & f - > samples )
bchannel_transmit ( call - > bchannel , f - > data , f - > samples ) ;
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
return 0 ;
2008-04-26 09:18:27 +00:00
}
2008-02-03 12:47:33 +00:00
2008-05-01 08:35:20 +00:00
static struct ast_frame * lcr_read ( struct ast_channel * ast )
2008-04-26 09:18:27 +00:00
{
2008-05-18 07:23:10 +00:00
struct chan_call * call ;
int i , len ;
unsigned char * p ;
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-05-18 07:23:10 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-05-19 17:39:39 +00:00
return NULL ;
2008-05-18 07:23:10 +00:00
}
2008-06-01 16:52:10 +00:00
if ( call - > pipe [ 0 ] > - 1 ) {
len = read ( call - > pipe [ 0 ] , call - > read_buff , sizeof ( call - > read_buff ) ) ;
if ( len < = 0 ) {
close ( call - > pipe [ 0 ] ) ;
call - > pipe [ 0 ] = - 1 ;
return NULL ;
}
}
2008-05-18 07:23:10 +00:00
2008-05-19 17:39:39 +00:00
p = call - > read_buff ;
for ( i = 0 ; i < len ; i + + ) {
* p = flip_bits [ * p ] ;
p + + ;
2008-05-18 07:23:10 +00:00
}
2008-05-19 17:39:39 +00:00
call - > read_fr . frametype = AST_FRAME_VOICE ;
2008-06-06 13:18:59 +00:00
call - > read_fr . subclass = ast - > nativeformats ;
2008-05-18 07:23:10 +00:00
call - > read_fr . datalen = len ;
call - > read_fr . samples = len ;
call - > read_fr . delivery = ast_tv ( 0 , 0 ) ;
2008-05-19 17:39:39 +00:00
call - > read_fr . data = call - > read_buff ;
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
return & call - > read_fr ;
2008-02-03 12:47:33 +00:00
}
2008-05-01 08:35:20 +00:00
static int lcr_indicate ( struct ast_channel * ast , int cond , const void * data , size_t datalen )
2008-04-26 09:18:27 +00:00
{
2008-05-01 08:35:20 +00:00
union parameter newparam ;
2008-06-01 16:52:10 +00:00
int res = 0 ;
2008-05-18 07:23:10 +00:00
struct chan_call * call ;
2008-04-29 06:33:06 +00:00
2008-05-01 18:07:02 +00:00
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-05-18 17:04:35 +00:00
CERROR ( NULL , ast , " Received indicate from Asterisk, but no call instance exists. \n " ) ;
2008-05-18 07:23:10 +00:00
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
2008-04-26 09:18:27 +00:00
switch ( cond ) {
case AST_CONTROL_BUSY :
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Received indicate AST_CONTROL_BUSY from Asterisk. \n " ) ;
2008-06-01 16:52:10 +00:00
ast_setstate ( ast , AST_STATE_BUSY ) ;
if ( call - > state ! = CHAN_LCR_STATE_OUT_DISCONNECT ) {
/* send message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . disconnectinfo . cause = 17 ;
newparam . disconnectinfo . location = LOCATION_PRIVATE_LOCAL ;
send_message ( MESSAGE_DISCONNECT , call - > ref , & newparam ) ;
/* change state */
call - > state = CHAN_LCR_STATE_OUT_DISCONNECT ;
}
break ;
2008-04-26 09:18:27 +00:00
case AST_CONTROL_CONGESTION :
2008-06-01 16:52:10 +00:00
CDEBUG ( call , ast , " Received indicate AST_CONTROL_CONGESTION from Asterisk. (cause %d) \n " , ast - > hangupcause ) ;
if ( call - > state ! = CHAN_LCR_STATE_OUT_DISCONNECT ) {
/* send message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . disconnectinfo . cause = ast - > hangupcause ;
newparam . disconnectinfo . location = LOCATION_PRIVATE_LOCAL ;
send_message ( MESSAGE_DISCONNECT , call - > ref , & newparam ) ;
/* change state */
call - > state = CHAN_LCR_STATE_OUT_DISCONNECT ;
}
break ;
case AST_CONTROL_PROCEEDING :
CDEBUG ( call , ast , " Received indicate AST_CONTROL_PROCEEDING from Asterisk. \n " ) ;
if ( call - > state = = CHAN_LCR_STATE_IN_SETUP
| | call - > state = = CHAN_LCR_STATE_IN_DIALING ) {
/* send message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
send_message ( MESSAGE_PROCEEDING , call - > ref , & newparam ) ;
/* change state */
call - > state = CHAN_LCR_STATE_IN_PROCEEDING ;
}
break ;
2008-05-01 08:35:20 +00:00
case AST_CONTROL_RINGING :
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Received indicate AST_CONTROL_RINGING from Asterisk. \n " ) ;
2008-06-01 16:52:10 +00:00
ast_setstate ( ast , AST_STATE_RINGING ) ;
if ( call - > state = = CHAN_LCR_STATE_IN_SETUP
| | call - > state = = CHAN_LCR_STATE_IN_DIALING
| | call - > state = = CHAN_LCR_STATE_IN_PROCEEDING ) {
/* send message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
send_message ( MESSAGE_ALERTING , call - > ref , & newparam ) ;
/* change state */
call - > state = CHAN_LCR_STATE_IN_ALERTING ;
}
break ;
2008-04-26 09:18:27 +00:00
case - 1 :
2008-06-01 16:52:10 +00:00
CDEBUG ( call , ast , " Received indicate -1. \n " ) ;
res = - 1 ;
break ;
2008-04-26 09:18:27 +00:00
case AST_CONTROL_VIDUPDATE :
2008-06-01 16:52:10 +00:00
CDEBUG ( call , ast , " Received indicate AST_CONTROL_VIDUPDATE. \n " ) ;
2008-04-26 09:18:27 +00:00
res = - 1 ;
break ;
case AST_CONTROL_HOLD :
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Received indicate AST_CONTROL_HOLD from Asterisk. \n " ) ;
2008-05-01 08:35:20 +00:00
/* send message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . notifyinfo . notify = INFO_NOTIFY_REMOTE_HOLD ;
send_message ( MESSAGE_NOTIFY , call - > ref , & newparam ) ;
2008-04-26 09:18:27 +00:00
break ;
case AST_CONTROL_UNHOLD :
2008-05-18 17:04:35 +00:00
CDEBUG ( call , ast , " Received indicate AST_CONTROL_UNHOLD from Asterisk. \n " ) ;
2008-05-01 08:35:20 +00:00
/* send message to lcr */
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
newparam . notifyinfo . notify = INFO_NOTIFY_REMOTE_RETRIEVAL ;
send_message ( MESSAGE_NOTIFY , call - > ref , & newparam ) ;
2008-04-26 09:18:27 +00:00
break ;
default :
2008-05-18 17:04:35 +00:00
CERROR ( call , ast , " Received indicate from Asterisk with unknown condition %d. \n " , cond ) ;
2008-06-01 16:52:10 +00:00
res = - 1 ;
break ;
2008-04-26 09:18:27 +00:00
}
2008-05-01 08:35:20 +00:00
/* return */
2008-05-01 18:07:02 +00:00
ast_mutex_unlock ( & chan_lock ) ;
2008-06-01 16:52:10 +00:00
return res ;
}
/*
* fixup asterisk
*/
static int lcr_fixup ( struct ast_channel * oldast , struct ast_channel * newast )
{
struct chan_call * call ;
ast_mutex_lock ( & chan_lock ) ;
call = oldast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-06-01 16:52:10 +00:00
CERROR ( NULL , oldast , " Received fixup from Asterisk, but no call instance exists. \n " ) ;
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
CDEBUG ( call , oldast , " Received fixup from Asterisk. \n " ) ;
call - > ast = newast ;
ast_mutex_lock ( & chan_lock ) ;
return 0 ;
}
/*
* send_text asterisk
*/
static int lcr_send_text ( struct ast_channel * ast , const char * text )
{
struct chan_call * call ;
union parameter newparam ;
ast_mutex_lock ( & chan_lock ) ;
call = ast - > tech_pvt ;
2008-06-06 13:18:59 +00:00
if ( ! call ) {
2008-06-01 16:52:10 +00:00
CERROR ( NULL , ast , " Received send_text from Asterisk, but no call instance exists. \n " ) ;
ast_mutex_unlock ( & chan_lock ) ;
return - 1 ;
}
CDEBUG ( call , ast , " Received send_text from Asterisk. (text=%s) \n " , text ) ;
memset ( & newparam , 0 , sizeof ( union parameter ) ) ;
strncpy ( newparam . notifyinfo . display , text , sizeof ( newparam . notifyinfo . display ) - 1 ) ;
send_message ( MESSAGE_NOTIFY , call - > ref , & newparam ) ;
ast_mutex_lock ( & chan_lock ) ;
return 0 ;
2008-04-26 09:18:27 +00:00
}
2008-02-03 12:47:33 +00:00
2008-05-01 18:07:02 +00:00
/*
* bridge process
*/
enum ast_bridge_result lcr_bridge ( struct ast_channel * ast1 ,
struct ast_channel * ast2 , int flags ,
struct ast_frame * * fo ,
struct ast_channel * * rc , int timeoutms )
{
struct chan_call * call1 , * call2 ;
struct ast_channel * carr [ 2 ] , * who ;
2008-06-06 13:18:59 +00:00
int to ;
2008-05-01 18:07:02 +00:00
struct ast_frame * f ;
int bridge_id ;
2008-05-18 17:04:35 +00:00
2008-05-25 14:12:20 +00:00
CDEBUG ( NULL , NULL , " Received briding request from Asterisk. \n " ) ;
2008-06-06 13:18:59 +00:00
carr [ 0 ] = ast1 ;
carr [ 1 ] = ast2 ;
2008-05-18 17:04:35 +00:00
2008-05-01 18:07:02 +00:00
/* join via dsp (if the channels are currently open) */
ast_mutex_lock ( & chan_lock ) ;
2008-05-18 07:23:10 +00:00
bridge_id = new_bridge_id ( ) ;
2008-05-01 18:07:02 +00:00
call1 = ast1 - > tech_pvt ;
call2 = ast2 - > tech_pvt ;
2008-05-18 07:23:10 +00:00
if ( call1 & & call2 )
2008-05-01 18:07:02 +00:00
{
call1 - > bridge_id = bridge_id ;
if ( call1 - > bchannel )
bchannel_join ( call1 - > bchannel , bridge_id ) ;
2008-05-18 07:23:10 +00:00
call1 - > bridge_call = call2 ;
2008-05-01 18:07:02 +00:00
}
if ( call2 )
{
call2 - > bridge_id = bridge_id ;
if ( call2 - > bchannel )
bchannel_join ( call2 - > bchannel , bridge_id ) ;
2008-05-18 07:23:10 +00:00
call2 - > bridge_call = call1 ;
2008-05-01 18:07:02 +00:00
}
ast_mutex_unlock ( & chan_lock ) ;
while ( 1 ) {
2008-06-06 13:18:59 +00:00
to = - 1 ;
2008-05-01 18:07:02 +00:00
who = ast_waitfor_n ( carr , 2 , & to ) ;
if ( ! who ) {
2008-05-25 14:12:20 +00:00
CDEBUG ( NULL , NULL , " Empty read on bridge, breaking out. \n " ) ;
2008-05-01 18:07:02 +00:00
break ;
}
f = ast_read ( who ) ;
if ( ! f | | f - > frametype = = AST_FRAME_CONTROL ) {
2008-06-06 13:18:59 +00:00
if ( ! f )
CDEBUG ( NULL , NULL , " Got hangup. \n " ) ;
else
CDEBUG ( NULL , NULL , " Got CONTROL. \n " ) ;
2008-05-01 18:07:02 +00:00
/* got hangup .. */
* fo = f ;
* rc = who ;
break ;
}
if ( f - > frametype = = AST_FRAME_DTMF ) {
2008-06-06 13:18:59 +00:00
CDEBUG ( NULL , NULL , " Got DTMF. \n " ) ;
2008-05-01 18:07:02 +00:00
* fo = f ;
* rc = who ;
break ;
}
if ( who = = ast1 ) {
ast_write ( ast2 , f ) ;
}
else {
ast_write ( ast1 , f ) ;
}
}
2008-05-25 14:12:20 +00:00
CDEBUG ( NULL , NULL , " Releasing bride. \n " ) ;
2008-05-18 17:04:35 +00:00
2008-05-01 18:07:02 +00:00
/* split channels */
ast_mutex_lock ( & chan_lock ) ;
call1 = ast1 - > tech_pvt ;
call2 = ast2 - > tech_pvt ;
if ( call1 )
{
call1 - > bridge_id = 0 ;
if ( call1 - > bchannel )
bchannel_join ( call1 - > bchannel , 0 ) ;
2008-05-18 07:23:10 +00:00
if ( call1 - > bridge_call )
call1 - > bridge_call - > bridge_call = NULL ;
call1 - > bridge_call = NULL ;
2008-05-01 18:07:02 +00:00
}
if ( call2 )
{
call2 - > bridge_id = 0 ;
if ( call2 - > bchannel )
bchannel_join ( call2 - > bchannel , 0 ) ;
2008-05-18 07:23:10 +00:00
if ( call2 - > bridge_call )
call2 - > bridge_call - > bridge_call = NULL ;
call2 - > bridge_call = NULL ;
2008-05-01 18:07:02 +00:00
}
ast_mutex_unlock ( & chan_lock ) ;
return AST_BRIDGE_COMPLETE ;
}
2008-05-25 14:12:20 +00:00
static struct ast_channel_tech lcr_tech = {
2008-05-19 17:47:05 +00:00
. type = " LCR " ,
2008-01-21 08:34:38 +00:00
. description = " Channel driver for connecting to Linux-Call-Router " ,
. requester = lcr_request ,
2008-05-01 18:07:02 +00:00
. send_digit_begin = lcr_digit ,
2008-01-21 08:34:38 +00:00
. call = lcr_call ,
2008-05-01 08:35:20 +00:00
. bridge = lcr_bridge ,
2008-01-21 08:34:38 +00:00
. hangup = lcr_hangup ,
. answer = lcr_answer ,
. read = lcr_read ,
. write = lcr_write ,
2008-04-26 09:18:27 +00:00
. indicate = lcr_indicate ,
2008-06-01 16:52:10 +00:00
. fixup = lcr_fixup ,
. send_text = lcr_send_text ,
2008-01-21 08:34:38 +00:00
. properties = 0
} ;
2008-04-26 10:25:01 +00:00
2008-04-26 08:32:30 +00:00
/*
* cli
*/
2008-06-06 13:18:59 +00:00
#if 0
2008-04-26 08:37:31 +00:00
static int lcr_show_lcr ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-04-26 08:37:31 +00:00
static int lcr_show_calls ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-04-26 08:37:31 +00:00
static int lcr_reload_routing ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-04-26 08:37:31 +00:00
static int lcr_reload_interfaces ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-04-26 08:37:31 +00:00
static int lcr_port_block ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-04-26 08:37:31 +00:00
static int lcr_port_unblock ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-04-26 08:37:31 +00:00
static int lcr_port_unload ( int fd , int argc , char * argv [ ] )
2008-04-26 08:32:30 +00:00
{
2008-05-01 18:07:02 +00:00
return 0 ;
2008-04-26 08:32:30 +00:00
}
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_show_lcr =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " show " , " lcr " , NULL } ,
lcr_show_lcr ,
" Shows current states of LCR core " ,
" Usage: lcr show lcr \n " ,
} ;
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_show_calls =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " show " , " calls " , NULL } ,
lcr_show_calls ,
" Shows current calls made by LCR and Asterisk " ,
" Usage: lcr show calls \n " ,
} ;
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_reload_routing =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " reload " , " routing " , NULL } ,
lcr_reload_routing ,
" Reloads routing conf of LCR, current uncomplete calls will be disconnected " ,
" Usage: lcr reload routing \n " ,
} ;
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_reload_interfaces =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " reload " , " interfaces " , NULL } ,
lcr_reload_interfaces ,
" Reloads interfaces conf of LCR " ,
" Usage: lcr reload interfaces \n " ,
} ;
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_port_block =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " port " , " block " , NULL } ,
lcr_port_block ,
" Blocks LCR port for further calls " ,
" Usage: lcr port block \" <port> \" \n " ,
} ;
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_port_unblock =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " port " , " unblock " , NULL } ,
lcr_port_unblock ,
" Unblocks or loads LCR port, port is opened my mISDN " ,
" Usage: lcr port unblock \" <port> \" \n " ,
} ;
2008-05-25 14:12:20 +00:00
static struct ast_cli_entry cli_port_unload =
2008-04-26 08:32:30 +00:00
{ { " lcr " , " port " , " unload " , NULL } ,
lcr_port_unload ,
" Unloads LCR port, port is closes by mISDN " ,
" Usage: lcr port unload \" <port> \" \n " ,
} ;
2008-06-06 13:18:59 +00:00
# endif
2008-04-26 08:32:30 +00:00
2008-01-21 08:34:38 +00:00
/*
* module loading and destruction
*/
2008-05-25 14:12:20 +00:00
int load_module ( void )
2008-01-21 08:34:38 +00:00
{
2008-06-01 16:52:10 +00:00
u_short i ;
2008-01-21 08:34:38 +00:00
2008-06-01 16:52:10 +00:00
for ( i = 0 ; i < 256 ; i + + ) {
2008-05-18 07:23:10 +00:00
flip_bits [ i ] = ( i > > 7 ) | ( ( i > > 5 ) & 2 ) | ( ( i > > 3 ) & 4 ) | ( ( i > > 1 ) & 8 )
2008-06-01 16:52:10 +00:00
| ( i < < 7 ) | ( ( i & 2 ) < < 5 ) | ( ( i & 4 ) < < 3 ) | ( ( i & 8 ) < < 1 ) ;
}
2008-01-21 08:34:38 +00:00
2008-06-06 13:18:59 +00:00
if ( read_options ( ) = = 0 ) {
CERROR ( NULL , NULL , " %s " , options_error ) ;
return AST_MODULE_LOAD_DECLINE ;
}
2008-05-01 18:07:02 +00:00
ast_mutex_init ( & chan_lock ) ;
2008-05-18 17:04:35 +00:00
ast_mutex_init ( & log_lock ) ;
2008-06-01 16:52:10 +00:00
if ( open_socket ( ) < 0 ) {
2008-01-21 08:34:38 +00:00
/* continue with closed socket */
}
2008-06-01 16:52:10 +00:00
if ( bchannel_initialize ( ) ) {
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Unable to open mISDN device \n " ) ;
2008-06-01 16:52:10 +00:00
close_socket ( ) ;
return AST_MODULE_LOAD_DECLINE ;
2008-01-21 08:34:38 +00:00
}
mISDN_created = 1 ;
2008-06-06 13:18:59 +00:00
lcr_tech . capabilities = ( options . law = = ' a ' ) ? AST_FORMAT_ALAW : AST_FORMAT_ULAW ;
2008-01-21 08:34:38 +00:00
if ( ast_channel_register ( & lcr_tech ) ) {
2008-05-18 17:04:35 +00:00
CERROR ( NULL , NULL , " Unable to register channel class \n " ) ;
2008-04-29 09:02:02 +00:00
bchannel_deinitialize ( ) ;
2008-06-01 16:52:10 +00:00
close_socket ( ) ;
return AST_MODULE_LOAD_DECLINE ;
2008-01-21 08:34:38 +00:00
}
2008-04-26 08:34:29 +00:00
#if 0
2008-02-03 12:47:33 +00:00
ast_cli_register ( & cli_show_lcr ) ;
ast_cli_register ( & cli_show_calls ) ;
2008-01-21 08:34:38 +00:00
2008-02-03 12:47:33 +00:00
ast_cli_register ( & cli_reload_routing ) ;
ast_cli_register ( & cli_reload_interfaces ) ;
ast_cli_register ( & cli_port_block ) ;
ast_cli_register ( & cli_port_unblock ) ;
2008-04-26 08:32:30 +00:00
ast_cli_register ( & cli_port_unload ) ;
2008-01-21 08:34:38 +00:00
ast_register_application ( " misdn_set_opt " , misdn_set_opt_exec , " misdn_set_opt " ,
" misdn_set_opt(:<opt><optarg>:<opt><optarg>..): \n "
" Sets mISDN opts. and optargs \n "
" \n "
" The available options are: \n "
" d - Send display text on called phone, text is the optparam \n "
" n - don't detect dtmf tones on called channel \n "
" h - make digital outgoing call \n "
" c - make crypted outgoing call, param is keyindex \n "
" e - perform echo cancelation on this channel, \n "
" takes taps as arguments (32,64,128,256) \n "
" s - send Non Inband DTMF as inband \n "
" vr - rxgain control \n "
" vt - txgain control \n "
) ;
2008-01-19 17:10:46 +00:00
2007-07-15 10:03:09 +00:00
2008-01-21 08:34:38 +00:00
lcr_cfg_get ( 0 , LCR_GEN_TRACEFILE , global_tracefile , BUFFERSIZE ) ;
2008-04-26 08:34:29 +00:00
= = = = = = =
2008-04-26 09:18:27 +00:00
//lcr_cfg_get( 0, LCR_GEN_TRACEFILE, global_tracefile, BUFFERSIZE);
2008-04-26 08:34:29 +00:00
# endif
2008-01-21 08:34:38 +00:00
2008-05-18 17:04:35 +00:00
quit = 0 ;
2008-05-01 18:07:02 +00:00
if ( ( pthread_create ( & chan_tid , NULL , chan_thread , NULL ) < 0 ) )
2008-04-29 07:38:49 +00:00
{
2008-05-01 18:07:02 +00:00
/* failed to create thread */
2008-04-29 09:02:02 +00:00
bchannel_deinitialize ( ) ;
2008-06-01 16:52:10 +00:00
close_socket ( ) ;
2008-04-29 09:02:02 +00:00
ast_channel_unregister ( & lcr_tech ) ;
2008-06-01 16:52:10 +00:00
return AST_MODULE_LOAD_DECLINE ;
2008-04-29 07:38:49 +00:00
}
2008-01-21 08:34:38 +00:00
return 0 ;
}
2008-05-25 14:12:20 +00:00
int unload_module ( void )
2008-01-21 08:34:38 +00:00
{
/* First, take us out of the channel loop */
2008-05-18 17:04:35 +00:00
CDEBUG ( NULL , NULL , " -- Unregistering mISDN Channel Driver -- \n " ) ;
2008-04-29 07:38:49 +00:00
quit = 1 ;
pthread_join ( chan_tid , NULL ) ;
2008-01-21 08:34:38 +00:00
ast_channel_unregister ( & lcr_tech ) ;
if ( mISDN_created ) {
bchannel_deinitialize ( ) ;
mISDN_created = 0 ;
2007-07-15 10:03:09 +00:00
}
2008-01-21 08:34:38 +00:00
if ( lcr_sock > = 0 ) {
close ( lcr_sock ) ;
lcr_sock = - 1 ;
}
return 0 ;
}
2008-05-19 20:07:40 +00:00
int reload_module ( void )
2008-01-21 08:34:38 +00:00
{
2008-04-26 09:18:27 +00:00
// reload_config();
2008-01-21 08:34:38 +00:00
return 0 ;
2007-07-15 10:03:09 +00:00
}
2008-06-01 16:52:10 +00:00
# define AST_MODULE "chan_lcr"
2007-07-15 10:03:09 +00:00
2008-06-01 16:52:10 +00:00
AST_MODULE_INFO ( ASTERISK_GPL_KEY , AST_MODFLAG_DEFAULT , " Channel driver for Linux-Call-Router Support (ISDN BRI/PRI) " ,
. load = load_module ,
. unload = unload_module ,
. reload = reload_module ,
) ;
2007-07-15 10:03:09 +00:00