2009-02-07 23:14:25 +00:00
/*
2012-04-25 17:14:55 -05:00
* Copyright ( c ) 2007 - 2012 , Anthony Minessale II
2010-11-10 21:17:02 +01:00
* Copyright ( c ) 2010 , Stefan Knoblich < s . knoblich @ axsentis . de >
2009-02-07 23:14:25 +00:00
* All rights reserved .
2010-11-06 16:08:07 +01:00
*
2009-02-07 23:14:25 +00:00
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
2010-11-06 16:08:07 +01:00
*
2009-02-07 23:14:25 +00:00
* * Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
2010-11-06 16:08:07 +01:00
*
2009-02-07 23:14:25 +00:00
* * Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
2010-11-06 16:08:07 +01:00
*
2009-02-07 23:14:25 +00:00
* * Neither the name of the original author ; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission .
2010-11-06 16:08:07 +01:00
*
*
2009-02-07 23:14:25 +00:00
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL ,
* EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO ,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR
* PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY , WHETHER IN CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING
* NEGLIGENCE OR OTHERWISE ) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE .
*/
2010-04-21 14:25:11 -04:00
# include "private/ftdm_core.h"
2010-01-15 19:22:49 +00:00
# include "ftmod_libpri.h"
2009-02-07 23:14:25 +00:00
2012-06-26 21:33:40 +02:00
static ftdm_status_t ftdm_libpri_start ( ftdm_span_t * span ) ;
static ftdm_io_interface_t ftdm_libpri_interface ;
2010-11-10 21:17:02 +01:00
static void _ftdm_channel_set_state_force ( ftdm_channel_t * chan , const ftdm_channel_state_t state )
{
assert ( chan ) ;
chan - > state = state ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Unloads libpri IO module
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_IO_UNLOAD_FUNCTION ( ftdm_libpri_unload )
2009-02-07 23:14:25 +00:00
{
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2009-02-07 23:14:25 +00:00
}
2010-04-27 14:32:36 -04:00
/**
* \ brief Returns the signalling status on a channel
* \ param ftdmchan Channel to get status on
* \ param status Pointer to set signalling status
* \ return Success or failure
*/
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION ( isdn_get_channel_sig_status )
{
* status = FTDM_SIG_STATE_DOWN ;
ftdm_libpri_data_t * isdn_data = ftdmchan - > span - > signal_data ;
if ( ftdm_test_flag ( & ( isdn_data - > spri ) , LPWRAP_PRI_READY ) ) {
* status = FTDM_SIG_STATE_UP ;
}
return FTDM_SUCCESS ;
}
/**
* \ brief Returns the signalling status on a span
* \ param span Span to get status on
* \ param status Pointer to set signalling status
* \ return Success or failure
*/
static FIO_SPAN_GET_SIG_STATUS_FUNCTION ( isdn_get_span_sig_status )
{
* status = FTDM_SIG_STATE_DOWN ;
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
if ( ftdm_test_flag ( & ( isdn_data - > spri ) , LPWRAP_PRI_READY ) ) {
* status = FTDM_SIG_STATE_UP ;
}
return FTDM_SUCCESS ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Starts a libpri channel ( outgoing call )
2010-01-15 19:22:49 +00:00
* \ param ftdmchan Channel to initiate call on
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-01-15 20:35:11 +00:00
static FIO_CHANNEL_OUTGOING_CALL_FUNCTION ( isdn_outgoing_call )
2009-02-07 23:14:25 +00:00
{
2011-02-25 09:58:15 -05:00
return FTDM_SUCCESS ;
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Requests an libpri channel on a span ( outgoing call )
* \ param span Span where to get a channel ( unused )
* \ param chan_id Specific channel to get ( 0 for any ) ( unused )
* \ param direction Call direction ( unused )
* \ param caller_data Caller information ( unused )
2010-01-15 19:22:49 +00:00
* \ param ftdmchan Channel to initialise ( unused )
2009-06-08 20:01:29 +00:00
* \ return Failure
*/
2010-01-15 20:35:11 +00:00
static FIO_CHANNEL_REQUEST_FUNCTION ( isdn_channel_request )
2009-02-07 23:14:25 +00:00
{
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2009-02-07 23:14:25 +00:00
}
2012-04-14 01:00:00 +02:00
2009-06-08 20:01:29 +00:00
/**
2012-04-14 01:00:00 +02:00
* \ brief Logs a libpri message
* \ param pri libpri structure
* \ param s Message string
2009-06-08 20:01:29 +00:00
*/
2012-04-14 01:00:00 +02:00
static void s_pri_message ( struct pri * pri , char * s )
{
struct lpwrap_pri * spri = pri_get_userdata ( pri ) ;
if ( spri & & spri - > dchan ) {
ftdm_log_chan ( spri - > dchan , FTDM_LOG_DEBUG , " %s " , s ) ;
} else {
ftdm_log ( FTDM_LOG_DEBUG , " %s " , s ) ;
}
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Logs a libpri error
2012-04-14 01:00:00 +02:00
* \ param pri libpri structure
* \ param s Error string
2009-06-08 20:01:29 +00:00
*/
2009-02-07 23:14:25 +00:00
static void s_pri_error ( struct pri * pri , char * s )
{
2012-04-14 01:00:00 +02:00
struct lpwrap_pri * spri = pri_get_userdata ( pri ) ;
2009-02-07 23:14:25 +00:00
2012-04-14 01:00:00 +02:00
if ( spri & & spri - > dchan ) {
ftdm_log_chan ( spri - > dchan , FTDM_LOG_ERROR , " %s " , s ) ;
} else {
ftdm_log ( FTDM_LOG_ERROR , " %s " , s ) ;
}
}
2009-03-19 20:15:39 +00:00
2010-11-11 00:03:06 +01:00
# define PRI_DEBUG_Q921_ALL (PRI_DEBUG_Q921_RAW | PRI_DEBUG_Q921_DUMP | PRI_DEBUG_Q921_STATE)
# define PRI_DEBUG_Q931_ALL (PRI_DEBUG_Q931_DUMP | PRI_DEBUG_Q931_STATE | PRI_DEBUG_Q931_ANOMALY)
2010-11-07 15:48:39 +01:00
static const struct ftdm_libpri_debug {
const char * name ;
const int flags ;
} ftdm_libpri_debug [ ] = {
2010-11-11 00:03:06 +01:00
/* NOTE: order is important for print_debug() */
{ " q921_all " , PRI_DEBUG_Q921_ALL } ,
2010-11-07 15:48:39 +01:00
{ " q921_raw " , PRI_DEBUG_Q921_RAW } ,
{ " q921_dump " , PRI_DEBUG_Q921_DUMP } ,
{ " q921_state " , PRI_DEBUG_Q921_STATE } ,
2010-11-11 00:03:06 +01:00
{ " q931_all " , PRI_DEBUG_Q931_ALL } ,
2010-11-07 15:48:39 +01:00
{ " q931_dump " , PRI_DEBUG_Q931_DUMP } ,
{ " q931_state " , PRI_DEBUG_Q931_STATE } ,
{ " q931_anomaly " , PRI_DEBUG_Q931_ANOMALY } ,
{ " config " , PRI_DEBUG_CONFIG } ,
{ " apdu " , PRI_DEBUG_APDU } ,
{ " aoc " , PRI_DEBUG_AOC }
} ;
2009-06-08 20:01:29 +00:00
/**
* \ brief Parses a debug string to flags
* \ param in Debug string to parse for
2010-11-07 15:48:39 +01:00
* \ return Flags or - 1 if nothing matched
2009-06-08 20:01:29 +00:00
*/
2010-11-10 22:42:18 +01:00
static int parse_debug ( const char * in , uint32_t * flags )
2009-02-09 19:13:02 +00:00
{
2010-11-07 15:48:39 +01:00
int res = - 1 ;
int i ;
2009-03-31 22:20:39 +00:00
2010-11-07 15:48:39 +01:00
if ( ! in | | ! flags )
return - 1 ;
2009-03-31 22:20:39 +00:00
2010-11-07 15:48:39 +01:00
if ( ! strcmp ( in , " all " ) ) {
* flags = PRI_DEBUG_ALL ;
return 0 ;
2009-02-09 19:13:02 +00:00
}
if ( strstr ( in , " none " ) ) {
2010-11-07 15:48:39 +01:00
* flags = 0 ;
return 0 ;
2009-02-09 19:13:02 +00:00
}
2010-11-14 17:48:53 +01:00
for ( i = 0 ; i < ftdm_array_len ( ftdm_libpri_debug ) ; i + + ) {
2010-11-07 15:48:39 +01:00
if ( strstr ( in , ftdm_libpri_debug [ i ] . name ) ) {
* flags | = ftdm_libpri_debug [ i ] . flags ;
res = 0 ;
}
}
return res ;
2009-02-09 19:13:02 +00:00
}
2011-08-05 22:50:58 -04:00
/**
* \ brief Parses a change status string to flags
* \ param in change status string to parse for
* \ return Flags
*/
static int parse_change_status ( const char * in )
{
int flags = 0 ;
if ( ! in ) {
return 0 ;
}
if ( strstr ( in , " in_service " ) | | strstr ( in , " in " ) ) {
flags = SERVICE_CHANGE_STATUS_INSERVICE ;
}
if ( strstr ( in , " maintenance " ) | | strstr ( in , " maint " ) ) {
flags = SERVICE_CHANGE_STATUS_MAINTENANCE ;
}
if ( strstr ( in , " out_of_service " ) | | strstr ( in , " out " ) ) {
flags = SERVICE_CHANGE_STATUS_OUTOFSERVICE ;
}
return flags ;
}
2010-11-11 00:03:06 +01:00
static int print_debug ( uint32_t flags , char * tmp , const int size )
{
int offset = 0 ;
int res = 0 ;
int i ;
if ( ( flags & PRI_DEBUG_ALL ) = = PRI_DEBUG_ALL ) {
strcat ( tmp , " all " ) ;
return 0 ;
}
else if ( ! flags ) {
strcat ( tmp , " none " ) ;
return 0 ;
}
2010-11-14 17:48:53 +01:00
for ( i = 0 ; i < ftdm_array_len ( ftdm_libpri_debug ) ; i + + ) {
2010-11-11 00:03:06 +01:00
if ( ( flags & ftdm_libpri_debug [ i ] . flags ) = = ftdm_libpri_debug [ i ] . flags ) {
res = snprintf ( & tmp [ offset ] , size - offset , " %s, " , ftdm_libpri_debug [ i ] . name ) ;
if ( res < = 0 | | res = = ( size - offset ) )
goto out ;
offset + = res ;
flags & = ~ ftdm_libpri_debug [ i ] . flags ; /* remove detected flags to make *_all work correctly */
}
}
out :
tmp [ offset - 1 ] = ' \0 ' ;
return 0 ;
}
2012-06-26 21:33:40 +02:00
/***************************************************************
* MSN filter
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-06-27 11:23:15 +02:00
/**
* Initialize MSN filter data structures
* \ param [ in ] isdn_data Span private data
* \ return FTDM_SUCCESS , FTDM_FAIL
*/
2012-06-26 21:33:40 +02:00
static int msn_filter_init ( ftdm_libpri_data_t * isdn_data )
{
if ( ! isdn_data )
return FTDM_FAIL ;
isdn_data - > msn_hash = create_hashtable ( 16 , ftdm_hash_hashfromstring , ftdm_hash_equalkeys ) ;
if ( ! isdn_data - > msn_hash )
return FTDM_FAIL ;
if ( ftdm_mutex_create ( & isdn_data - > msn_mutex ) ) {
hashtable_destroy ( isdn_data - > msn_hash ) ;
return FTDM_FAIL ;
}
return FTDM_SUCCESS ;
}
2012-06-27 11:23:15 +02:00
/**
* Destroy MSN filter data structures
* \ param [ in ] isdn_data Span private data
* \ return FTDM_SUCCESS , FTDM_FAIL
*/
2012-06-26 21:33:40 +02:00
static int msn_filter_destroy ( ftdm_libpri_data_t * isdn_data )
{
if ( ! isdn_data )
return FTDM_FAIL ;
if ( isdn_data - > msn_hash )
hashtable_destroy ( isdn_data - > msn_hash ) ;
if ( isdn_data - > msn_mutex )
ftdm_mutex_destroy ( & isdn_data - > msn_mutex ) ;
return FTDM_SUCCESS ;
}
2012-06-27 11:23:15 +02:00
/**
* Check if the given string is a valid MSN / DDI
* ( i . e . : Not empty , not longer than FDM_DIGITS_LIMIT and all numbers )
* \ param [ in ] str String to check
* \ return FTDM_SUCCESS , FTDM_FAIL
*/
2012-06-26 21:33:40 +02:00
static int msn_filter_verify ( const char * str )
{
if ( ftdm_strlen_zero ( str ) | | strlen ( str ) > = FTDM_DIGITS_LIMIT )
return FTDM_FALSE ;
if ( ftdm_is_number ( str ) ! = FTDM_SUCCESS )
return FTDM_FALSE ;
return FTDM_TRUE ;
}
2012-06-27 11:23:15 +02:00
/**
* Add a new MSN / DDI to the filter
* \ param [ in ] isdn_data Span private data
* \ param [ in ] msn New MSN / DDI to add
* \ return FTDM_SUCCESS , FTDM_FAIL
*/
2012-06-26 21:33:40 +02:00
static int msn_filter_add ( ftdm_libpri_data_t * isdn_data , const char * msn )
{
static const int value = 0xdeadbeef ;
char * key = NULL ;
int ret = FTDM_SUCCESS ;
if ( ! isdn_data | | ! msn_filter_verify ( msn ) )
return FTDM_FAIL ;
ftdm_mutex_lock ( isdn_data - > msn_mutex ) ;
/* check for duplicates (ignore if already in set) */
if ( hashtable_search ( isdn_data - > msn_hash , ( void * ) msn ) ) {
ret = FTDM_SUCCESS ;
goto out ;
}
/* Copy MSN (transient string), hashtable will free it in hashtable_destroy() */
key = ftdm_strdup ( msn ) ;
if ( ! key ) {
ret = FTDM_FAIL ;
goto out ;
}
/* add MSN to list/hash */
if ( ! hashtable_insert ( isdn_data - > msn_hash , ( void * ) key , ( void * ) & value , HASHTABLE_FLAG_FREE_KEY ) ) {
ftdm_safe_free ( key ) ;
ret = FTDM_FAIL ;
}
out :
ftdm_mutex_unlock ( isdn_data - > msn_mutex ) ;
return ret ;
}
/**
2012-06-27 11:23:15 +02:00
* Check if a DNIS ( destination number ) is a valid MSN / DDI
* \ param [ in ] isdn_data Span private data
* \ param [ in ] msn Number to check
* \ retval FTDM_TRUE \ p msn is a valid MSN / DDI or filter list is empty
* \ retval FTDM_FALSE \ p msn is not a valid MSN / DDI
2012-06-26 21:33:40 +02:00
*/
static int msn_filter_match ( ftdm_libpri_data_t * isdn_data , const char * msn )
{
int ret = FTDM_FALSE ;
if ( ! isdn_data )
2012-06-27 11:23:15 +02:00
return FTDM_FALSE ;
2012-06-26 21:33:40 +02:00
/* No number? return match found */
if ( ftdm_strlen_zero ( msn ) )
return FTDM_TRUE ;
ftdm_mutex_lock ( isdn_data - > msn_mutex ) ;
/* No MSN configured? */
if ( hashtable_count ( isdn_data - > msn_hash ) < = 0 ) {
ret = FTDM_TRUE ;
goto out ;
}
/* Search for a matching MSN */
if ( hashtable_search ( isdn_data - > msn_hash , ( void * ) msn ) )
ret = FTDM_TRUE ;
out :
ftdm_mutex_unlock ( isdn_data - > msn_mutex ) ;
return ret ;
}
2012-06-27 11:23:15 +02:00
/**
* Helper function to iterate over MSNs in the filter hash ( handles locking )
* \ param [ in ] isdn_data Span private data
* \ param [ in ] func Callback function that is invoked for each entry
* \ param [ in ] data Private data passed to callback
* \ return FTDM_SUCCESS , FTDM_FAIL
*/
2012-06-26 21:33:40 +02:00
static int msn_filter_foreach ( ftdm_libpri_data_t * isdn_data , int ( * func ) ( const char * , void * ) , void * data )
{
ftdm_hash_iterator_t * iter = NULL ;
int ret = FTDM_SUCCESS ;
if ( ! isdn_data | | ! func )
return FTDM_FAIL ;
/* iterate over MSNs */
ftdm_mutex_lock ( isdn_data - > msn_mutex ) ;
for ( iter = hashtable_first ( isdn_data - > msn_hash ) ; iter ; iter = hashtable_next ( iter ) ) {
2012-07-18 13:27:33 +02:00
const void * msn = NULL ;
2012-06-26 21:33:40 +02:00
2012-07-18 13:27:33 +02:00
hashtable_this ( iter , & msn , NULL , NULL ) ;
2012-06-26 21:33:40 +02:00
2012-07-18 13:27:33 +02:00
if ( ftdm_strlen_zero ( ( const char * ) msn ) )
2012-06-26 21:33:40 +02:00
break ;
if ( ( ret = func ( msn , data ) ) ! = FTDM_SUCCESS )
break ;
}
ftdm_mutex_unlock ( isdn_data - > msn_mutex ) ;
return ret ;
}
/***************************************************************
* Module API ( CLI ) interface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-02-09 19:13:02 +00:00
2010-11-06 16:08:07 +01:00
static const char * ftdm_libpri_usage =
" Usage: \n "
" libpri kill <span> \n "
2011-08-05 22:50:58 -04:00
" libpri reset <span> \n "
" libpri restart <span> <channel/all> \n "
" libpri maintenance <span> <channel/all> <in/maint/out> \n "
2010-11-11 00:03:06 +01:00
" libpri debug <span> [all|none|flag,...flagN] \n "
2012-06-26 21:33:40 +02:00
" libpri msn <span> \n "
2010-11-07 15:48:39 +01:00
" \n "
" Possible debug flags: \n "
" \t q921_raw - Q.921 Raw messages \n "
" \t q921_dump - Q.921 Decoded messages \n "
" \t q921_state - Q.921 State machine changes \n "
" \t q921_all - Enable all Q.921 debug options \n "
" \n "
" \t q931_dump - Q.931 Messages \n "
" \t q931_state - Q.931 State machine changes \n "
" \t q931_anomaly - Q.931 Anomalies \n "
" \t q931_all - Enable all Q.931 debug options \n "
" \n "
" \t apdu - Application protocol data unit \n "
" \t aoc - Advice of Charge messages \n "
" \t config - Configuration \n "
" \n "
" \t none - Disable debugging \n "
" \t all - Enable all debug options \n " ;
2009-02-09 19:13:02 +00:00
2012-06-26 21:33:40 +02:00
/**
* Custom data handle for list iterator functions
*/
struct msn_list_cb_private {
ftdm_stream_handle_t * stream ;
unsigned int count ;
} ;
2012-06-27 11:23:15 +02:00
/**
* " ftdm libpri msn <span> " API command callback
* function for msn_filter_foreach ( )
*/
2012-06-26 21:33:40 +02:00
static int msn_list_cb ( const char * msn , void * priv )
{
struct msn_list_cb_private * data = priv ;
ftdm_stream_handle_t * stream = data - > stream ;
if ( ! stream | | ftdm_strlen_zero ( msn ) )
return FTDM_FAIL ;
stream - > write_function ( stream , " \t %s \n " , msn ) ;
data - > count + + ;
return FTDM_SUCCESS ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief API function to kill or debug a libpri span
* \ param stream API stream handler
* \ param data String containing argurments
* \ return Flags
*/
2010-01-15 20:35:11 +00:00
static FIO_API_FUNCTION ( ftdm_libpri_api )
2009-02-09 19:13:02 +00:00
{
char * mycmd = NULL , * argv [ 10 ] = { 0 } ;
2010-11-06 16:08:07 +01:00
int argc = 0 ;
2009-02-09 19:13:02 +00:00
if ( data ) {
2010-01-15 19:22:49 +00:00
mycmd = ftdm_strdup ( data ) ;
argc = ftdm_separate_string ( mycmd , ' ' , argv , ( sizeof ( argv ) / sizeof ( argv [ 0 ] ) ) ) ;
2009-02-09 19:13:02 +00:00
}
2010-11-06 16:08:07 +01:00
if ( argc = = 1 ) {
if ( ! strcasecmp ( argv [ 0 ] , " help " ) | | ! strcasecmp ( argv [ 0 ] , " usage " ) ) {
stream - > write_function ( stream , ftdm_libpri_usage ) ;
goto done ;
}
2011-11-18 22:23:15 +01:00
} else if ( argc = = 2 ) {
2009-03-11 02:04:18 +00:00
if ( ! strcasecmp ( argv [ 0 ] , " kill " ) ) {
int span_id = atoi ( argv [ 1 ] ) ;
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2009-03-11 02:04:18 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdm_span_find_by_name ( argv [ 1 ] , & span ) = = FTDM_SUCCESS | | ftdm_span_find ( span_id , & span ) = = FTDM_SUCCESS ) {
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2009-03-11 02:04:18 +00:00
2010-01-15 19:22:49 +00:00
if ( span - > start ! = ftdm_libpri_start ) {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR '%s' is not a libpri span. \n " ,
__FILE__ , ftdm_span_get_name ( span ) ) ;
2009-03-11 02:04:18 +00:00
goto done ;
}
2010-11-10 21:17:02 +01:00
ftdm_clear_flag ( & ( isdn_data - > spri ) , LPWRAP_PRI_READY ) ;
2009-03-11 02:04:18 +00:00
stream - > write_function ( stream , " %s: +OK killed. \n " , __FILE__ ) ;
goto done ;
} else {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR span '%s' not found. \n " ,
__FILE__ , argv [ 0 ] ) ;
2009-03-11 02:04:18 +00:00
goto done ;
}
}
2012-06-26 21:33:40 +02:00
if ( ! strcasecmp ( argv [ 0 ] , " msn " ) ) {
ftdm_span_t * span = NULL ;
struct msn_list_cb_private data ;
data . stream = stream ;
data . count = 0 ;
if ( ftdm_span_find_by_name ( argv [ 1 ] , & span ) ! = FTDM_SUCCESS ) {
stream - > write_function ( stream , " %s: -ERR span '%s' not found. \n " ,
__FILE__ , argv [ 1 ] ) ;
goto done ;
}
if ( span - > start ! = ftdm_libpri_start ) {
stream - > write_function ( stream , " %s: -ERR '%s' is not a libpri span. \n " ,
__FILE__ , ftdm_span_get_name ( span ) ) ;
goto done ;
}
/* header */
stream - > write_function ( stream , " ------------------------------------------------------------------------------ \n " ) ;
if ( msn_filter_foreach ( span - > signal_data , msn_list_cb , & data ) ) {
stream - > write_function ( stream , " -ERR: Failed to list MSN(s) \n " ) ;
goto done ;
}
if ( data . count = = 0 ) {
stream - > write_function ( stream , " \t \t \t -- no entries -- \n " ) ;
}
/* footer */
stream - > write_function ( stream , " ---------------------------------------------------------------[ %02d MSN(s) ]-- \n " ,
data . count ) ;
stream - > write_function ( stream , " +OK " ) ;
goto done ;
}
2011-11-18 22:23:15 +01:00
} else if ( argc > = 2 ) {
2009-02-09 19:13:02 +00:00
if ( ! strcasecmp ( argv [ 0 ] , " debug " ) ) {
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = NULL ;
2009-02-09 19:13:02 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdm_span_find_by_name ( argv [ 1 ] , & span ) = = FTDM_SUCCESS ) {
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2010-11-10 22:42:18 +01:00
uint32_t flags = 0 ;
2010-11-07 15:48:39 +01:00
2010-01-15 19:22:49 +00:00
if ( span - > start ! = ftdm_libpri_start ) {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR '%s' is not a libpri span. \n " ,
__FILE__ , ftdm_span_get_name ( span ) ) ;
2009-03-11 02:04:18 +00:00
goto done ;
}
2010-11-11 00:03:06 +01:00
if ( argc = = 2 ) {
char tmp [ 100 ] = { 0 } ;
print_debug ( pri_get_debug ( isdn_data - > spri . pri ) , tmp , sizeof ( tmp ) ) ;
stream - > write_function ( stream , " %s: +OK current debug flags: '%s' \n " , __FILE__ , tmp ) ;
goto done ;
}
2010-11-07 15:48:39 +01:00
if ( parse_debug ( argv [ 2 ] , & flags ) = = - 1 ) {
stream - > write_function ( stream , " %s: -ERR invalid debug flags given \n " , __FILE__ ) ;
goto done ;
}
pri_set_debug ( isdn_data - > spri . pri , flags ) ;
stream - > write_function ( stream , " %s: +OK debug %s. \n " , __FILE__ , ( flags ) ? " enabled " : " disabled " ) ;
2009-02-09 19:13:02 +00:00
goto done ;
} else {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR span '%s' not found. \n " ,
__FILE__ , argv [ 0 ] ) ;
2009-02-09 19:13:02 +00:00
goto done ;
}
}
2011-08-05 22:50:58 -04:00
if ( ! strcasecmp ( argv [ 0 ] , " reset " ) ) {
ftdm_span_t * span = NULL ;
if ( ftdm_span_find_by_name ( argv [ 1 ] , & span ) = = FTDM_SUCCESS ) {
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2011-11-18 23:02:07 +01:00
2011-08-05 22:50:58 -04:00
if ( span - > start ! = ftdm_libpri_start ) {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR '%s' is not a libpri span. \n " ,
__FILE__ , ftdm_span_get_name ( span ) ) ;
2011-08-05 22:50:58 -04:00
goto done ;
}
pri_restart ( isdn_data - > spri . pri ) ;
stream - > write_function ( stream , " %s: +OK reset. \n " , __FILE__ ) ;
goto done ;
} else {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR span '%s' not found. \n " ,
__FILE__ , argv [ 0 ] ) ;
2011-08-05 22:50:58 -04:00
goto done ;
}
}
if ( ! strcasecmp ( argv [ 0 ] , " restart " ) & & argc = = 3 ) {
ftdm_span_t * span = NULL ;
if ( ftdm_span_find_by_name ( argv [ 1 ] , & span ) = = FTDM_SUCCESS ) {
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2011-11-18 23:02:07 +01:00
2011-08-05 22:50:58 -04:00
if ( span - > start ! = ftdm_libpri_start ) {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR '%s' is not a libpri span. \n " ,
__FILE__ , ftdm_span_get_name ( span ) ) ;
2011-08-05 22:50:58 -04:00
goto done ;
}
if ( ! strcasecmp ( argv [ 2 ] , " all " ) ) {
int j ;
for ( j = 1 ; j < = span - > chan_count ; j + + ) {
pri_reset ( isdn_data - > spri . pri , j ) ;
ftdm_sleep ( 50 ) ;
}
} else {
pri_reset ( isdn_data - > spri . pri , atoi ( argv [ 2 ] ) ) ;
}
stream - > write_function ( stream , " %s: +OK restart set. \n " , __FILE__ ) ;
goto done ;
} else {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR span '%s' not found. \n " ,
__FILE__ , argv [ 0 ] ) ;
2011-08-05 22:50:58 -04:00
goto done ;
}
}
if ( ! strcasecmp ( argv [ 0 ] , " maintenance " ) & & argc > 3 ) {
ftdm_span_t * span = NULL ;
if ( ftdm_span_find_by_name ( argv [ 1 ] , & span ) = = FTDM_SUCCESS ) {
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2011-11-18 23:02:07 +01:00
2011-08-05 22:50:58 -04:00
if ( span - > start ! = ftdm_libpri_start ) {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR '%s' is not a libpri span. \n " ,
__FILE__ , ftdm_span_get_name ( span ) ) ;
2011-08-05 22:50:58 -04:00
goto done ;
}
if ( ! isdn_data - > service_message_support ) {
stream - > write_function ( stream , " %s: -ERR service message support is disabled \n " , __FILE__ ) ;
goto done ;
}
if ( ! strcasecmp ( argv [ 2 ] , " all " ) ) {
int j ;
for ( j = 1 ; j < = span - > chan_count ; j + + ) {
pri_maintenance_service ( isdn_data - > spri . pri , atoi ( argv [ 1 ] ) , j , parse_change_status ( argv [ 3 ] ) ) ;
ftdm_sleep ( 50 ) ;
}
} else {
pri_maintenance_service ( isdn_data - > spri . pri , atoi ( argv [ 1 ] ) , atoi ( argv [ 2 ] ) , parse_change_status ( argv [ 3 ] ) ) ;
}
stream - > write_function ( stream , " %s: +OK change status set. \n " , __FILE__ ) ;
goto done ;
} else {
2011-11-18 23:02:07 +01:00
stream - > write_function ( stream , " %s: -ERR span '%s' not found. \n " ,
__FILE__ , argv [ 0 ] ) ;
2011-08-05 22:50:58 -04:00
goto done ;
}
}
2011-11-18 22:23:15 +01:00
} else {
/* zero args print usage */
stream - > write_function ( stream , ftdm_libpri_usage ) ;
goto done ;
2009-02-09 19:13:02 +00:00
}
2011-08-05 22:50:58 -04:00
2009-02-09 19:13:02 +00:00
stream - > write_function ( stream , " %s: -ERR invalid command. \n " , __FILE__ ) ;
2010-11-06 16:08:07 +01:00
done :
2010-01-15 19:22:49 +00:00
ftdm_safe_free ( mycmd ) ;
2009-02-09 19:13:02 +00:00
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2009-02-09 19:13:02 +00:00
}
2010-11-06 16:08:07 +01:00
2009-06-08 20:01:29 +00:00
/**
* \ brief Loads libpri IO module
2010-01-15 20:35:11 +00:00
* \ param fio FreeTDM IO interface
2009-06-08 20:01:29 +00:00
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_IO_LOAD_FUNCTION ( ftdm_libpri_io_init )
2009-02-09 19:13:02 +00:00
{
2010-01-15 20:35:11 +00:00
assert ( fio ! = NULL ) ;
2009-02-09 19:13:02 +00:00
2010-11-06 16:08:07 +01:00
memset ( & ftdm_libpri_interface , 0 , sizeof ( ftdm_libpri_interface ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_libpri_interface . name = " libpri " ;
2010-11-06 16:08:07 +01:00
ftdm_libpri_interface . api = & ftdm_libpri_api ;
2009-02-09 19:13:02 +00:00
2010-01-15 20:35:11 +00:00
* fio = & ftdm_libpri_interface ;
2009-02-09 19:13:02 +00:00
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2009-02-09 19:13:02 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Loads libpri signaling module
2010-01-15 20:35:11 +00:00
* \ param fio FreeTDM IO interface
2009-06-08 20:01:29 +00:00
* \ return Success
*/
2010-01-15 20:35:11 +00:00
static FIO_SIG_LOAD_FUNCTION ( ftdm_libpri_init )
2009-02-07 23:14:25 +00:00
{
pri_set_error ( s_pri_error ) ;
pri_set_message ( s_pri_message ) ;
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief libpri state map
*/
2010-01-15 19:22:49 +00:00
static ftdm_state_map_t isdn_state_map = {
2009-02-07 23:14:25 +00:00
{
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_ANY_STATE } ,
{ FTDM_CHANNEL_STATE_RESTART , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_RESTART , FTDM_END } ,
{ FTDM_CHANNEL_STATE_DOWN , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_DOWN , FTDM_END } ,
{ FTDM_CHANNEL_STATE_DIALING , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_DIALING , FTDM_END } ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP ,
FTDM_CHANNEL_STATE_PROCEED , FTDM_CHANNEL_STATE_RINGING , FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_CHANNEL_STATE_PROGRESS ,
FTDM_CHANNEL_STATE_UP , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_PROCEED , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP ,
FTDM_CHANNEL_STATE_RINGING , FTDM_CHANNEL_STATE_PROGRESS , FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_CHANNEL_STATE_UP , FTDM_END } ,
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_RINGING , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP ,
FTDM_CHANNEL_STATE_PROGRESS , FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_CHANNEL_STATE_UP , FTDM_END } ,
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_PROGRESS , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP ,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_UP , FTDM_END }
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_UP , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_UP , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_TERMINATING , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
2011-01-13 23:09:51 +01:00
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_END }
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP_COMPLETE , FTDM_END } ,
} ,
{
ZSD_OUTBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_HANGUP_COMPLETE , FTDM_END } ,
{ FTDM_CHANNEL_STATE_DOWN , FTDM_END } ,
} ,
2009-02-07 23:14:25 +00:00
/****************************************/
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_ANY_STATE } ,
{ FTDM_CHANNEL_STATE_RESTART , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_RESTART , FTDM_END } ,
{ FTDM_CHANNEL_STATE_DOWN , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_DOWN , FTDM_END } ,
2011-06-29 13:26:51 +02:00
{ FTDM_CHANNEL_STATE_DIALTONE , FTDM_CHANNEL_STATE_COLLECT , FTDM_CHANNEL_STATE_RING , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_DIALTONE , FTDM_END } ,
{ FTDM_CHANNEL_STATE_RING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_TERMINATING , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
2011-06-29 13:26:51 +02:00
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_COLLECT , FTDM_END } ,
{ FTDM_CHANNEL_STATE_RING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_TERMINATING , FTDM_END }
} ,
2009-02-07 23:14:25 +00:00
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_RING , FTDM_END } ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_PROCEED , FTDM_CHANNEL_STATE_RINGING , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_PROCEED , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_RINGING , FTDM_CHANNEL_STATE_PROGRESS ,
FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_CHANNEL_STATE_UP , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_RINGING , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_PROGRESS , FTDM_CHANNEL_STATE_PROGRESS_MEDIA ,
FTDM_CHANNEL_STATE_UP , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2011-01-13 23:09:51 +01:00
{ FTDM_CHANNEL_STATE_PROGRESS , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_CHANNEL_STATE_UP , FTDM_END }
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_PROGRESS_MEDIA , FTDM_END } ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_UP , FTDM_END }
2009-02-07 23:14:25 +00:00
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
2010-01-15 19:22:49 +00:00
{ FTDM_CHANNEL_STATE_UP , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_CHANNEL_STATE_TERMINATING , FTDM_END } ,
2009-02-07 23:14:25 +00:00
} ,
2011-01-13 23:09:51 +01:00
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_TERMINATING , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_END } ,
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_HANGUP , FTDM_END } ,
{ FTDM_CHANNEL_STATE_HANGUP_COMPLETE , FTDM_END } ,
} ,
{
ZSD_INBOUND ,
ZSM_UNACCEPTABLE ,
{ FTDM_CHANNEL_STATE_HANGUP_COMPLETE , FTDM_END } ,
{ FTDM_CHANNEL_STATE_DOWN , FTDM_END } ,
} ,
2009-02-07 23:14:25 +00:00
}
} ;
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for channel state change
2010-01-15 19:22:49 +00:00
* \ param ftdmchan Channel to handle
2010-11-25 12:33:36 -05:00
* \ note This function MUST be called with the channel locked
2009-06-08 20:01:29 +00:00
*/
2010-12-31 13:44:20 -05:00
static ftdm_status_t state_advance ( ftdm_channel_t * chan )
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_libpri_data_t * isdn_data = chan - > span - > signal_data ;
q931_call * call = ( q931_call * ) chan - > call_data ;
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
ftdm_sigmsg_t sig ;
2009-02-07 23:14:25 +00:00
2010-11-16 22:50:43 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- %d:%d STATE [%s] \n " ,
2010-11-10 21:17:02 +01:00
ftdm_channel_get_span_id ( chan ) , ftdm_channel_get_id ( chan ) , ftdm_channel_get_state_str ( chan ) ) ;
2009-02-07 23:14:25 +00:00
memset ( & sig , 0 , sizeof ( sig ) ) ;
2010-11-10 21:17:02 +01:00
sig . chan_id = ftdm_channel_get_id ( chan ) ;
sig . span_id = ftdm_channel_get_span_id ( chan ) ;
sig . channel = chan ;
2011-05-03 13:02:01 +02:00
2010-12-31 13:44:20 -05:00
ftdm_channel_complete_state ( chan ) ;
2009-02-07 23:14:25 +00:00
2010-11-10 21:17:02 +01:00
switch ( ftdm_channel_get_state ( chan ) ) {
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_DOWN :
2009-02-07 23:14:25 +00:00
{
2010-12-18 02:24:28 +01:00
ftdm_channel_t * chtmp = chan ;
2011-05-03 13:02:01 +02:00
if ( call ) {
pri_destroycall ( isdn_data - > spri . pri , call ) ;
chan - > call_data = NULL ;
}
2010-12-18 02:24:28 +01:00
if ( ftdm_channel_close ( & chtmp ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_WARNING , " -- Failed to close channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
} else {
ftdm_log ( FTDM_LOG_DEBUG , " -- Closed channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
2010-11-16 22:50:43 +01:00
}
2009-02-07 23:14:25 +00:00
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_PROGRESS :
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
if ( ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
2010-01-15 19:22:49 +00:00
sig . event_id = FTDM_SIGEVENT_PROGRESS ;
2010-11-10 21:17:02 +01:00
if ( ( status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ! = FTDM_SUCCESS ) ) {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
2009-02-07 23:14:25 +00:00
}
} else if ( call ) {
2011-01-13 23:09:51 +01:00
pri_progress ( isdn_data - > spri . pri , call , ftdm_channel_get_id ( chan ) , 0 ) ;
} else {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
}
}
break ;
case FTDM_CHANNEL_STATE_RINGING :
{
if ( ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
sig . event_id = FTDM_SIGEVENT_RINGING ;
if ( ( status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ! = FTDM_SUCCESS ) ) {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
}
} else if ( call ) {
// pri_progress(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 1);
pri_acknowledge ( isdn_data - > spri . pri , call , ftdm_channel_get_id ( chan ) , 1 ) ;
2009-02-07 23:14:25 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
}
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA :
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
if ( ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
2010-01-15 19:22:49 +00:00
sig . event_id = FTDM_SIGEVENT_PROGRESS_MEDIA ;
2010-11-10 21:17:02 +01:00
if ( ( status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ! = FTDM_SUCCESS ) ) {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
2009-02-07 23:14:25 +00:00
}
} else if ( call ) {
2010-11-16 22:50:43 +01:00
/* make sure channel is open in this state (outbound handled in on_proceeding()) */
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) ) {
ftdm_channel_open_chan ( chan ) ;
}
2011-01-13 23:09:51 +01:00
pri_progress ( isdn_data - > spri . pri , call , ftdm_channel_get_id ( chan ) , 1 ) ;
} else {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
}
}
break ;
case FTDM_CHANNEL_STATE_PROCEED :
{
if ( ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
/* PROCEED from other end, notify user */
sig . event_id = FTDM_SIGEVENT_PROCEED ;
if ( ( status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ! = FTDM_SUCCESS ) ) {
ftdm_log ( FTDM_LOG_ERROR , " Failed to send PROCEED sigevent on Channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
}
} else if ( call ) {
pri_proceeding ( isdn_data - > spri . pri , call , ftdm_channel_get_id ( chan ) , 0 ) ;
2009-02-07 23:14:25 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
}
}
break ;
2010-11-10 21:17:02 +01:00
2011-06-29 13:26:51 +02:00
case FTDM_CHANNEL_STATE_COLLECT : /* Overlap receive */
{
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
if ( ! call ) {
ftdm_log_chan_msg ( chan , FTDM_LOG_ERROR , " No call handle \n " ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
}
else if ( pri_need_more_info ( isdn_data - > spri . pri , call , ftdm_channel_get_id ( chan ) , 0 ) ) {
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
ftdm_log_chan_msg ( chan , FTDM_LOG_ERROR , " Failed to send INFORMATION request \n " ) ;
/* hangup call */
caller_data - > hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
}
} else {
ftdm_log_chan_msg ( chan , FTDM_LOG_ERROR , " Overlap receiving on outbound call? \n " ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
}
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_RING :
2009-02-07 23:14:25 +00:00
{
2010-11-16 22:50:43 +01:00
/*
* This needs more auditing for BRI PTMP :
2011-01-13 23:09:51 +01:00
* does pri_acknowledge ( ) steal the call from other devices ? ( yes , it does )
2010-11-16 22:50:43 +01:00
*/
2010-11-10 21:17:02 +01:00
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
2009-02-07 23:14:25 +00:00
if ( call ) {
2011-01-13 23:09:51 +01:00
pri_proceeding ( isdn_data - > spri . pri , call , ftdm_channel_get_id ( chan ) , 0 ) ;
// pri_acknowledge(isdn_data->spri.pri, call, ftdm_channel_get_id(chan), 0);
2010-01-15 19:22:49 +00:00
sig . event_id = FTDM_SIGEVENT_START ;
2010-11-10 21:17:02 +01:00
if ( ( status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ! = FTDM_SUCCESS ) ) {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
2009-02-07 23:14:25 +00:00
}
} else {
2010-11-10 21:17:02 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
}
}
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_RESTART :
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
chan - > caller_data . hangup_cause = FTDM_CAUSE_NORMAL_UNSPECIFIED ;
2010-01-15 19:22:49 +00:00
sig . event_id = FTDM_SIGEVENT_RESTART ;
2010-11-10 21:17:02 +01:00
status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_DOWN ) ;
2009-02-07 23:14:25 +00:00
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_UP :
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
if ( ftdm_test_flag ( chan , FTDM_CHANNEL_OUTBOUND ) ) {
2010-01-15 19:22:49 +00:00
sig . event_id = FTDM_SIGEVENT_UP ;
2010-11-10 21:17:02 +01:00
if ( ( status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ! = FTDM_SUCCESS ) ) {
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
2009-02-07 23:14:25 +00:00
}
} else if ( call ) {
2010-11-16 22:50:43 +01:00
/* make sure channel is open in this state (outbound handled in on_answer()) */
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) ) {
ftdm_channel_open_chan ( chan ) ;
}
2009-02-07 23:14:25 +00:00
pri_answer ( isdn_data - > spri . pri , call , 0 , 1 ) ;
} else {
2010-11-10 21:17:02 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
}
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_DIALING :
2009-02-07 23:14:25 +00:00
if ( isdn_data ) {
2010-11-10 21:17:02 +01:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
2009-02-07 23:14:25 +00:00
struct pri_sr * sr ;
2010-11-10 21:17:02 +01:00
int ton ;
2009-03-02 22:05:11 +00:00
2009-02-07 23:14:25 +00:00
if ( ! ( call = pri_new_call ( isdn_data - > spri . pri ) ) ) {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Failed to create new call on channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) , ftdm_channel_get_id ( chan ) ) ;
/* TODO: set hangup cause? */
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
2010-12-31 13:44:20 -05:00
return FTDM_SUCCESS ;
2009-02-07 23:14:25 +00:00
}
2010-11-10 21:17:02 +01:00
ton = caller_data - > dnis . type ;
switch ( ton ) {
2010-01-15 19:22:49 +00:00
case FTDM_TON_NATIONAL :
2010-11-10 21:17:02 +01:00
ton = PRI_NATIONAL_ISDN ;
2009-03-02 22:05:11 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_TON_INTERNATIONAL :
2010-11-10 21:17:02 +01:00
ton = PRI_INTERNATIONAL_ISDN ;
2009-03-02 22:05:11 +00:00
break ;
2010-01-15 19:22:49 +00:00
case FTDM_TON_SUBSCRIBER_NUMBER :
2010-11-10 21:17:02 +01:00
ton = PRI_LOCAL_ISDN ;
2009-03-02 22:05:11 +00:00
break ;
default :
2010-11-10 22:42:18 +01:00
ton = isdn_data - > ton ;
2009-03-02 22:05:11 +00:00
}
2010-11-10 21:17:02 +01:00
chan - > call_data = call ;
2009-02-07 23:14:25 +00:00
sr = pri_sr_new ( ) ;
2010-11-10 21:17:02 +01:00
if ( ! sr ) {
ftdm_log ( FTDM_LOG_ERROR , " Failed to create new setup request on channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) , ftdm_channel_get_id ( chan ) ) ;
/* TODO: handle error properly */
}
2009-02-07 23:14:25 +00:00
assert ( sr ) ;
2010-11-10 21:17:02 +01:00
2011-07-23 12:53:04 -04:00
pri_sr_set_channel ( sr , ftdm_channel_get_id ( chan ) , 1 , 0 ) ;
2010-11-10 22:42:18 +01:00
pri_sr_set_bearer ( sr , PRI_TRANS_CAP_SPEECH , isdn_data - > layer1 ) ;
2010-11-10 21:17:02 +01:00
pri_sr_set_called ( sr , caller_data - > dnis . digits , ton , 1 ) ;
pri_sr_set_caller ( sr , caller_data - > cid_num . digits ,
( ( isdn_data - > opts & FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ) ? NULL : caller_data - > cid_name ) ,
ton ,
( ( caller_data - > pres ! = 1 ) ? PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN : PRES_PROHIB_USER_NUMBER_NOT_SCREENED ) ) ;
2009-04-10 19:50:36 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ( isdn_data - > opts & FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE ) ) {
2010-11-10 21:17:02 +01:00
pri_sr_set_redirecting ( sr , caller_data - > cid_num . digits , ton ,
2010-11-06 16:08:07 +01:00
PRES_ALLOWED_USER_NUMBER_PASSED_SCREEN , PRI_REDIR_UNCONDITIONAL ) ;
2009-04-10 19:50:36 +00:00
}
2010-11-08 00:43:09 +01:00
# ifdef HAVE_LIBPRI_AOC
if ( isdn_data - > opts & FTMOD_LIBPRI_OPT_FACILITY_AOC ) {
/* request AOC on call */
pri_sr_set_aoc_charging_request ( sr , ( PRI_AOC_REQUEST_S | PRI_AOC_REQUEST_E | PRI_AOC_REQUEST_D ) ) ;
ftdm_log ( FTDM_LOG_DEBUG , " Requesting AOC-S/D/E on call \n " ) ;
}
# endif
2009-02-07 23:14:25 +00:00
if ( pri_setup ( isdn_data - > spri . pri , call , sr ) ) {
2010-11-10 21:17:02 +01:00
caller_data - > hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
2009-02-07 23:14:25 +00:00
}
pri_sr_free ( sr ) ;
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_HANGUP :
2009-02-07 23:14:25 +00:00
{
2009-02-10 16:41:03 +00:00
if ( call ) {
2010-11-10 21:17:02 +01:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
pri_hangup ( isdn_data - > spri . pri , call , caller_data - > hangup_cause ) ;
2011-01-13 23:09:51 +01:00
// pri_destroycall(isdn_data->spri.pri, call);
2011-05-03 13:02:01 +02:00
// chan->call_data = NULL;
2010-11-06 16:08:07 +01:00
}
2011-01-13 23:09:51 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_HANGUP_COMPLETE ) ;
2009-02-07 23:14:25 +00:00
}
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE :
2011-01-13 23:09:51 +01:00
{
2011-05-03 13:02:01 +02:00
// if (call) {
// pri_destroycall(isdn_data->spri.pri, call);
// chan->call_data = NULL;
// }
2011-01-13 23:09:51 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_DOWN ) ;
}
2009-02-07 23:14:25 +00:00
break ;
2010-11-10 21:17:02 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_CHANNEL_STATE_TERMINATING :
2009-02-07 23:14:25 +00:00
{
2010-01-15 19:22:49 +00:00
sig . event_id = FTDM_SIGEVENT_STOP ;
2010-11-10 21:17:02 +01:00
status = ftdm_span_send_signal ( ftdm_channel_get_span ( chan ) , & sig ) ;
2010-10-05 13:12:43 -04:00
/* user moves us to HANGUP and from there we go to DOWN */
2009-02-07 23:14:25 +00:00
}
default :
break ;
}
2010-12-31 13:44:20 -05:00
return FTDM_SUCCESS ;
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Checks current state on a span
* \ param span Span to check status on
*/
2010-01-15 19:22:49 +00:00
static __inline__ void check_state ( ftdm_span_t * span )
2009-02-07 23:14:25 +00:00
{
2010-11-06 16:08:07 +01:00
if ( ftdm_test_flag ( span , FTDM_SPAN_STATE_CHANGE ) ) {
uint32_t j ;
ftdm_clear_flag_locked ( span , FTDM_SPAN_STATE_CHANGE ) ;
2010-11-10 21:17:02 +01:00
for ( j = 1 ; j < = ftdm_span_get_chan_count ( span ) ; j + + ) {
ftdm_channel_t * chan = ftdm_span_get_channel ( span , j ) ;
2010-11-24 12:30:58 -05:00
ftdm_channel_lock ( chan ) ;
2010-12-31 13:44:20 -05:00
ftdm_channel_advance_states ( chan ) ;
2010-11-24 12:30:58 -05:00
ftdm_channel_unlock ( chan ) ;
2010-11-06 16:08:07 +01:00
}
}
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri information event ( incoming call ? )
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_info ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2011-06-29 13:26:51 +02:00
ftdm_span_t * span = spri - > span ;
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > ring . channel ) ;
ftdm_caller_data_t * caller_data = NULL ;
if ( ! chan ) {
2012-07-11 22:38:25 +02:00
ftdm_log ( FTDM_LOG_CRIT , " -- Info on channel %d:%d but it's not in use? \n " , ftdm_span_get_id ( span ) , pevent - > ring . channel ) ;
2011-06-29 13:26:51 +02:00
return 0 ;
}
caller_data = ftdm_channel_get_caller_data ( chan ) ;
2010-11-10 21:17:02 +01:00
2011-06-29 13:26:51 +02:00
switch ( ftdm_channel_get_state ( chan ) ) {
case FTDM_CHANNEL_STATE_COLLECT : /* TE-mode overlap receiving */
ftdm_log_chan ( chan , FTDM_LOG_DEBUG , " -- Incoming INFORMATION indication, current called number: '%s', number complete: %s \n " ,
pevent - > ring . callednum , pevent - > ring . complete ? " yes " : " no " ) ;
2011-06-30 12:55:56 +02:00
/* append digits to dnis */
if ( ! ftdm_strlen_zero ( pevent - > ring . callednum ) ) {
int digits = strlen ( pevent - > ring . callednum ) ;
int offset = strlen ( caller_data - > dnis . digits ) ;
2012-08-23 22:26:49 +02:00
int len = 0 ;
2011-06-30 12:55:56 +02:00
2012-08-23 22:26:49 +02:00
if ( strchr ( pevent - > ring . callednum , ' # ' ) ) {
pevent - > ring . complete = 1 ;
digits - - ;
}
len = ftdm_min ( sizeof ( caller_data - > dnis . digits ) - 1 - offset , digits ) ; /* max. length without terminator */
2011-06-30 12:55:56 +02:00
if ( len < digits ) {
ftdm_log_chan ( chan , FTDM_LOG_WARNING , " Length %d of digit string exceeds available space %d of DNIS, truncating! \n " ,
digits , len ) ;
}
2012-08-23 22:26:49 +02:00
if ( len ) {
ftdm_copy_string ( & caller_data - > dnis . digits [ offset ] , ( char * ) pevent - > ring . callednum , len + 1 ) ; /* max. length with terminator */
caller_data - > dnis . digits [ offset + len ] = ' \0 ' ;
}
2011-06-30 12:55:56 +02:00
}
2011-06-29 13:26:51 +02:00
if ( pevent - > ring . complete ) {
ftdm_log_chan_msg ( chan , FTDM_LOG_DEBUG , " Number complete indicated, moving channel to RING state \n " ) ;
/* notify switch */
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_RING ) ;
}
break ;
case FTDM_CHANNEL_STATE_DIALTONE : /* NT-mode overlap receiving */
ftdm_log_chan ( chan , FTDM_LOG_DEBUG , " -- Incoming INFORMATION indication, current called number: '%s' \n " ,
pevent - > ring . callednum ) ;
/* Need to add proper support for overlap receiving in NT-mode (requires FreeSWITCH + FreeTDM core support) */
if ( strlen ( pevent - > ring . callednum ) > 3 ) {
ftdm_log ( FTDM_LOG_DEBUG , " final number is: %s \n " , pevent - > ring . callednum ) ;
pri_answer ( spri - > pri , pevent - > ring . call , 0 , 1 ) ;
}
break ;
default :
ftdm_log_chan ( chan , FTDM_LOG_ERROR , " -- INFORMATION indication on channel %d:%d in invalid state '%s' \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ,
ftdm_channel_get_state_str ( chan ) ) ;
2009-02-07 23:14:25 +00:00
}
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri hangup event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_hangup ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > hangup . channel ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
if ( ! chan ) {
2012-07-11 22:38:25 +02:00
ftdm_log ( FTDM_LOG_CRIT , " -- Hangup on channel %d:%d but it's not in use? \n " , ftdm_span_get_id ( spri - > span ) , pevent - > hangup . channel ) ;
2010-10-05 13:12:43 -04:00
return 0 ;
2009-02-07 23:14:25 +00:00
}
2010-11-10 21:17:02 +01:00
ftdm_channel_lock ( chan ) ;
2010-10-05 13:12:43 -04:00
2011-05-03 13:02:01 +02:00
switch ( event_type ) {
case LPWRAP_PRI_EVENT_HANGUP_REQ : /* DISCONNECT */
if ( ftdm_channel_get_state ( chan ) > = FTDM_CHANNEL_STATE_TERMINATING ) {
ftdm_log_chan ( chan , FTDM_LOG_DEBUG , " Ignoring remote hangup in state %s \n " ,
ftdm_channel_get_state_str ( chan ) ) ;
goto done ;
}
ftdm_log ( FTDM_LOG_DEBUG , " -- Hangup REQ on channel %d:%d \n " ,
ftdm_span_get_id ( spri - > span ) , pevent - > hangup . channel ) ;
pri_hangup ( spri - > pri , pevent - > hangup . call , pevent - > hangup . cause ) ;
chan - > caller_data . hangup_cause = pevent - > hangup . cause ;
2011-06-29 13:26:51 +02:00
switch ( ftdm_channel_get_state ( chan ) ) {
case FTDM_CHANNEL_STATE_DIALTONE :
case FTDM_CHANNEL_STATE_COLLECT :
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_HANGUP ) ;
break ;
default :
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_TERMINATING ) ;
}
2011-05-03 13:02:01 +02:00
break ;
case LPWRAP_PRI_EVENT_HANGUP_ACK : /* */
ftdm_log ( FTDM_LOG_DEBUG , " -- Hangup ACK on channel %d:%d \n " ,
ftdm_span_get_id ( spri - > span ) , pevent - > hangup . channel ) ;
2010-10-05 13:12:43 -04:00
2011-05-03 13:02:01 +02:00
pri_hangup ( spri - > pri , pevent - > hangup . call , pevent - > hangup . cause ) ;
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_HANGUP_COMPLETE ) ;
break ;
2010-11-10 21:17:02 +01:00
2011-05-03 13:02:01 +02:00
case LPWRAP_PRI_EVENT_HANGUP : /* "RELEASE/RELEASE_COMPLETE/other" */
ftdm_log ( FTDM_LOG_DEBUG , " -- Hangup on channel %d:%d \n " ,
ftdm_span_get_id ( spri - > span ) , pevent - > hangup . channel ) ;
switch ( ftdm_channel_get_state ( chan ) ) {
case FTDM_CHANNEL_STATE_DIALING :
case FTDM_CHANNEL_STATE_RINGING :
case FTDM_CHANNEL_STATE_PROGRESS :
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA :
case FTDM_CHANNEL_STATE_PROCEED :
case FTDM_CHANNEL_STATE_UP :
chan - > caller_data . hangup_cause = pevent - > hangup . cause ;
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_TERMINATING ) ;
break ;
case FTDM_CHANNEL_STATE_HANGUP :
chan - > caller_data . hangup_cause = pevent - > hangup . cause ;
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_HANGUP_COMPLETE ) ;
break ;
// case FTDM_CHANNEL_STATE_TERMINATING:
// ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP);
// break;
// case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
// ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN);
// break;
}
break ;
default :
break ;
}
2010-10-05 13:12:43 -04:00
2010-11-10 21:17:02 +01:00
done :
ftdm_channel_unlock ( chan ) ;
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri answer event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_answer ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > answer . channel ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
if ( chan ) {
2010-11-16 22:50:43 +01:00
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) ) {
ftdm_log ( FTDM_LOG_DEBUG , " -- Call answered, opening B-Channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
if ( ftdm_channel_open_chan ( chan ) ! = FTDM_SUCCESS ) {
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
ftdm_log ( FTDM_LOG_ERROR , " -- Error opening channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
caller_data - > hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_TERMINATING ) ;
goto out ;
}
}
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Answer on channel %d:%d \n " , ftdm_span_get_id ( span ) , pevent - > answer . channel ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_UP ) ;
2009-02-07 23:14:25 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Answer on channel %d:%d but it's not in the span? \n " ,
ftdm_span_get_id ( span ) , pevent - > answer . channel ) ;
2009-02-07 23:14:25 +00:00
}
2010-11-16 22:50:43 +01:00
out :
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
2010-11-16 22:50:43 +01:00
* \ brief Handler for libpri proceeding event
2009-06-08 20:01:29 +00:00
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2010-11-16 22:50:43 +01:00
static int on_proceeding ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
2010-11-16 22:50:43 +01:00
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > proceeding . channel ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
if ( chan ) {
2010-11-16 22:50:43 +01:00
/* Open channel if inband information is available */
2011-10-28 15:18:58 -04:00
if ( pevent - > proceeding . progressmask & PRI_PROG_INBAND_AVAILABLE | | pevent - > proceeding . progressmask & PRI_PROG_CALL_NOT_E2E_ISDN ) {
2011-03-10 18:25:43 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- In-band information available, B-Channel %d:%d \n " ,
2010-11-16 22:50:43 +01:00
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
2011-03-10 18:25:43 +01:00
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) & & ( ftdm_channel_open_chan ( chan ) ! = FTDM_SUCCESS ) ) {
2010-11-16 22:50:43 +01:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
ftdm_log ( FTDM_LOG_ERROR , " -- Error opening channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
caller_data - > hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_TERMINATING ) ;
goto out ;
}
}
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Proceeding on channel %d:%d \n " , ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
2011-01-13 23:09:51 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_PROCEED ) ;
2009-02-07 23:14:25 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Proceeding on channel %d:%d but it's not in the span? \n " ,
ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
2009-02-07 23:14:25 +00:00
}
2010-11-16 22:50:43 +01:00
out :
return 0 ;
}
/**
* \ brief Handler for libpri progress event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
* \ note also uses pri_event - > proceeding
*/
static int on_progress ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
{
ftdm_span_t * span = spri - > span ;
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > proceeding . channel ) ;
if ( chan ) {
/* Open channel if inband information is available */
2011-10-28 15:18:58 -04:00
if ( pevent - > proceeding . progressmask & PRI_PROG_INBAND_AVAILABLE | | pevent - > proceeding . progressmask & PRI_PROG_CALL_NOT_E2E_ISDN ) {
2011-03-10 18:25:43 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- In-band information available, B-Channel %d:%d \n " ,
2010-11-16 22:50:43 +01:00
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
2011-03-10 18:25:43 +01:00
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) & & ( ftdm_channel_open_chan ( chan ) ! = FTDM_SUCCESS ) ) {
2010-11-16 22:50:43 +01:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
ftdm_log ( FTDM_LOG_ERROR , " -- Error opening channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
caller_data - > hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_TERMINATING ) ;
goto out ;
}
2011-01-13 23:09:51 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Progress on channel %d:%d with media \n " , ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_PROGRESS_MEDIA ) ;
} else {
ftdm_log ( FTDM_LOG_DEBUG , " -- Progress on channel %d:%d \n " , ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_PROGRESS ) ;
2010-11-16 22:50:43 +01:00
}
} else {
ftdm_log ( FTDM_LOG_DEBUG , " -- Progress on channel %d:%d but it's not in the span? \n " ,
ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
}
out :
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri ringing event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_ringing ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > ringing . channel ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
if ( chan ) {
2010-01-15 19:22:49 +00:00
/* we may get on_ringing even when we're already in FTDM_CHANNEL_STATE_PROGRESS_MEDIA */
2011-01-13 23:09:51 +01:00
// if (ftdm_channel_get_state(chan) == FTDM_CHANNEL_STATE_PROGRESS_MEDIA) {
// /* dont try to move to STATE_PROGRESS to avoid annoying veto warning */
// return 0;
// }
2010-11-16 22:50:43 +01:00
/* Open channel if inband information is available */
2011-03-10 18:25:43 +01:00
if ( ( pevent - > ringing . progressmask & PRI_PROG_INBAND_AVAILABLE ) ) {
ftdm_log ( FTDM_LOG_DEBUG , " -- In-band information available, B-Channel %d:%d \n " ,
2010-11-16 22:50:43 +01:00
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
2011-03-10 18:25:43 +01:00
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) & & ( ftdm_channel_open_chan ( chan ) ! = FTDM_SUCCESS ) ) {
2010-11-16 22:50:43 +01:00
ftdm_caller_data_t * caller_data = ftdm_channel_get_caller_data ( chan ) ;
ftdm_log ( FTDM_LOG_ERROR , " -- Error opening channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
caller_data - > hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_TERMINATING ) ;
goto out ;
}
2011-03-10 18:25:43 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Ringing on channel %d:%d with media \n " , ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_PROGRESS_MEDIA ) ;
} else {
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_PROGRESS);
ftdm_log ( FTDM_LOG_DEBUG , " -- Ringing on channel %d:%d \n " , ftdm_span_get_id ( span ) , pevent - > proceeding . channel ) ;
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RINGING ) ;
2010-11-16 22:50:43 +01:00
}
2009-02-07 23:14:25 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Ringing on channel %d:%d but it's not in the span? \n " ,
ftdm_span_get_id ( span ) , pevent - > ringing . channel ) ;
2009-02-07 23:14:25 +00:00
}
2010-11-16 22:50:43 +01:00
out :
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri ring event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0 on success
*/
2009-02-07 23:14:25 +00:00
static int on_ring ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
2011-06-29 13:26:51 +02:00
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2012-06-26 21:33:40 +02:00
ftdm_channel_t * chan = NULL ;
2010-11-10 21:17:02 +01:00
ftdm_caller_data_t * caller_data = NULL ;
2009-02-07 23:14:25 +00:00
int ret = 0 ;
2012-06-26 21:33:40 +02:00
if ( pevent - > ring . channel = = - 1 ) {
ftdm_log ( FTDM_LOG_ERROR , " -- New call without channel on span '%s' [NOTE: Initial SETUP w/o channel selection is not supported by FreeTDM] \n " ,
ftdm_span_get_name ( span ) ) ;
pri_destroycall ( spri - > pri , pevent - > ring . call ) ;
return ret ;
}
chan = ftdm_span_get_channel ( span , pevent - > ring . channel ) ;
2010-11-16 22:50:43 +01:00
if ( ! chan ) {
2012-06-26 21:33:40 +02:00
ftdm_log ( FTDM_LOG_ERROR , " -- Unable to get channel %d:%d \n " ,
ftdm_span_get_id ( span ) , pevent - > ring . channel ) ;
pri_hangup ( spri - > pri , pevent - > ring . call , PRI_CAUSE_DESTINATION_OUT_OF_ORDER ) ;
return ret ;
}
/* check MSN filter */
if ( ! msn_filter_match ( isdn_data , pevent - > ring . callednum ) ) {
ftdm_log ( FTDM_LOG_INFO , " -- MSN filter not matching incoming DNIS '%s', ignoring call \n " ,
pevent - > ring . callednum ) ;
pri_destroycall ( spri - > pri , pevent - > ring . call ) ;
2010-11-25 12:33:36 -05:00
return ret ;
}
ftdm_channel_lock ( chan ) ;
if ( chan - > call_data ) {
/* we could drop the incoming call, but most likely the pointer is just a ghost of the past,
* this check is just to detect potentially unreleased pointers */
ftdm_log_chan ( chan , FTDM_LOG_ERROR , " channel already has call %p! \n " , chan - > call_data ) ;
chan - > call_data = NULL ;
2009-02-07 23:14:25 +00:00
}
2010-11-16 22:50:43 +01:00
if ( ftdm_channel_get_state ( chan ) ! = FTDM_CHANNEL_STATE_DOWN | | ftdm_test_flag ( chan , FTDM_CHANNEL_INUSE ) ) {
ftdm_log ( FTDM_LOG_WARNING , " -- Duplicate Ring on channel %d:%d (ignored) \n " , ftdm_span_get_id ( span ) , pevent - > ring . channel ) ;
2009-02-07 23:14:25 +00:00
goto done ;
}
2010-11-16 22:50:43 +01:00
if ( ( pevent - > ring . progressmask & PRI_PROG_INBAND_AVAILABLE ) ) {
/* Open channel if inband information is available */
ftdm_log ( FTDM_LOG_DEBUG , " -- In-band information available, opening B-Channel %d:%d \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
if ( ! ftdm_test_flag ( chan , FTDM_CHANNEL_OPEN ) & & ftdm_channel_open_chan ( chan ) ! = FTDM_SUCCESS ) {
// ftdm_caller_data_t *caller_data = ftdm_channel_get_caller_data(chan);
ftdm_log ( FTDM_LOG_WARNING , " -- Error opening channel %d:%d (ignored) \n " ,
ftdm_channel_get_span_id ( chan ) ,
ftdm_channel_get_id ( chan ) ) ;
// caller_data->hangup_cause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
// ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
// goto done;
}
} else {
/* Reserve channel, don't open it yet */
if ( ftdm_channel_use ( chan ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_WARNING , " -- Error reserving channel %d:%d (ignored) \n " ,
ftdm_span_get_id ( span ) , pevent - > ring . channel ) ;
goto done ;
}
}
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_NOTICE , " -- Ring on channel %d:%d (from %s to %s) \n " , ftdm_span_get_id ( span ) , pevent - > ring . channel ,
2009-02-07 23:14:25 +00:00
pevent - > ring . callingnum , pevent - > ring . callednum ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
caller_data = ftdm_channel_get_caller_data ( chan ) ;
memset ( caller_data , 0 , sizeof ( * caller_data ) ) ;
ftdm_set_string ( caller_data - > cid_num . digits , ( char * ) pevent - > ring . callingnum ) ;
ftdm_set_string ( caller_data - > ani . digits , ( char * ) pevent - > ring . callingani ) ;
ftdm_set_string ( caller_data - > dnis . digits , ( char * ) pevent - > ring . callednum ) ;
2010-11-15 11:38:45 +01:00
ftdm_set_string ( caller_data - > rdnis . digits , ( char * ) pevent - > ring . redirectingnum ) ;
2010-11-06 16:08:07 +01:00
2010-01-15 19:22:49 +00:00
if ( ! ftdm_strlen_zero ( ( char * ) pevent - > ring . callingname ) ) {
2010-11-10 21:17:02 +01:00
ftdm_set_string ( caller_data - > cid_name , ( char * ) pevent - > ring . callingname ) ;
2009-02-11 22:47:44 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_set_string ( caller_data - > cid_name , ( char * ) pevent - > ring . callingnum ) ;
2009-02-11 22:47:44 +00:00
}
2010-11-06 16:08:07 +01:00
2009-02-07 23:14:25 +00:00
if ( pevent - > ring . ani2 > = 0 ) {
2010-11-10 21:17:02 +01:00
snprintf ( caller_data - > aniII , 5 , " %.2d " , pevent - > ring . ani2 ) ;
2009-02-07 23:14:25 +00:00
}
2010-11-06 16:08:07 +01:00
2009-02-07 23:14:25 +00:00
// scary to trust this pointer, you'd think they would give you a copy of the call data so you own it......
2010-11-16 22:50:43 +01:00
/* hurr, this is valid as along as nobody releases the call */
2010-11-10 21:17:02 +01:00
chan - > call_data = pevent - > ring . call ;
2010-11-06 16:08:07 +01:00
2011-06-29 13:26:51 +02:00
/* only go to RING state if we have the complete called number (indicated via pevent->complete flag) */
if ( ! pevent - > ring . complete & & ( isdn_data - > overlap & FTMOD_LIBPRI_OVERLAP_RECEIVE ) ) {
ftdm_log ( FTDM_LOG_DEBUG , " RING event without complete indicator, waiting for more digits \n " ) ;
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_COLLECT ) ;
} else {
ftdm_log ( FTDM_LOG_DEBUG , " RING event with complete indicator (or overlap receive disabled) \n " ) ;
ftdm_set_state ( chan , FTDM_CHANNEL_STATE_RING ) ;
}
2010-11-06 16:08:07 +01:00
done :
2010-11-25 12:33:36 -05:00
ftdm_channel_unlock ( chan ) ;
2009-02-07 23:14:25 +00:00
return ret ;
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 19:22:49 +00:00
* \ brief Processes freetdm event
2009-06-08 20:01:29 +00:00
* \ param span Span on which the event was fired
* \ param event Event to be treated
* \ return Success or failure
*/
2010-01-15 19:22:49 +00:00
static __inline__ ftdm_status_t process_event ( ftdm_span_t * span , ftdm_event_t * event )
2009-04-22 21:22:42 +00:00
{
2010-04-21 14:25:11 -04:00
ftdm_alarm_flag_t alarmbits ;
2010-11-06 16:08:07 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " EVENT [%s][%d][%d:%d] STATE [%s] \n " ,
ftdm_oob_event2str ( event - > enum_id ) ,
event - > enum_id ,
2010-11-10 21:17:02 +01:00
ftdm_channel_get_span_id ( event - > channel ) ,
ftdm_channel_get_id ( event - > channel ) ,
ftdm_channel_get_state_str ( event - > channel ) ) ;
2009-04-22 21:22:42 +00:00
2010-11-10 21:17:02 +01:00
switch ( event - > enum_id ) {
2010-01-15 19:22:49 +00:00
case FTDM_OOB_ALARM_TRAP :
2009-04-22 21:22:42 +00:00
{
2010-11-10 21:17:02 +01:00
if ( ftdm_channel_get_state ( event - > channel ) ! = FTDM_CHANNEL_STATE_DOWN ) {
if ( ftdm_channel_get_type ( event - > channel ) = = FTDM_CHAN_TYPE_B ) {
2010-01-15 19:22:49 +00:00
ftdm_set_state_locked ( event - > channel , FTDM_CHANNEL_STATE_RESTART ) ;
2009-04-22 21:22:42 +00:00
}
}
2010-01-15 19:22:49 +00:00
ftdm_set_flag ( event - > channel , FTDM_CHANNEL_SUSPENDED ) ;
2009-04-22 21:22:42 +00:00
2010-04-21 14:25:11 -04:00
ftdm_channel_get_alarms ( event - > channel , & alarmbits ) ;
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_WARNING , " channel %d:%d (%d:%d) has alarms! [%s] \n " ,
ftdm_channel_get_span_id ( event - > channel ) , ftdm_channel_get_id ( event - > channel ) ,
ftdm_channel_get_ph_span_id ( event - > channel ) , ftdm_channel_get_ph_id ( event - > channel ) ,
ftdm_channel_get_last_error ( event - > channel ) ) ;
2009-04-22 21:22:42 +00:00
}
break ;
2010-01-15 19:22:49 +00:00
case FTDM_OOB_ALARM_CLEAR :
2009-04-22 21:22:42 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_WARNING , " channel %d:%d (%d:%d) alarms Cleared! \n " ,
ftdm_channel_get_span_id ( event - > channel ) , ftdm_channel_get_id ( event - > channel ) ,
ftdm_channel_get_ph_span_id ( event - > channel ) , ftdm_channel_get_ph_id ( event - > channel ) ) ;
2009-04-22 21:22:42 +00:00
2010-01-15 19:22:49 +00:00
ftdm_clear_flag ( event - > channel , FTDM_CHANNEL_SUSPENDED ) ;
2010-04-21 14:25:11 -04:00
ftdm_channel_get_alarms ( event - > channel , & alarmbits ) ;
2009-04-22 21:22:42 +00:00
}
break ;
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2009-04-22 21:22:42 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Checks for events on a span
* \ param span Span to check for events
*/
2010-01-15 19:22:49 +00:00
static __inline__ void check_events ( ftdm_span_t * span )
2009-04-22 21:22:42 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_status_t status ;
2009-04-22 21:22:42 +00:00
2010-09-23 17:51:45 -03:00
status = ftdm_span_poll_event ( span , 5 , NULL ) ;
2009-04-22 21:22:42 +00:00
2010-11-10 21:17:02 +01:00
switch ( status ) {
2010-01-15 19:22:49 +00:00
case FTDM_SUCCESS :
2009-04-22 21:22:42 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_event_t * event ;
2010-11-06 16:08:07 +01:00
2010-01-15 19:22:49 +00:00
while ( ftdm_span_next_event ( span , & event ) = = FTDM_SUCCESS ) {
if ( event - > enum_id = = FTDM_OOB_NOOP ) {
2009-04-22 21:22:42 +00:00
continue ;
}
2010-01-15 19:22:49 +00:00
if ( process_event ( span , event ) ! = FTDM_SUCCESS ) {
2009-04-22 21:22:42 +00:00
break ;
}
}
}
break ;
2010-11-06 16:08:07 +01:00
2010-01-15 19:22:49 +00:00
case FTDM_FAIL :
2010-11-06 16:08:07 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " Event Failure! %d \n " , ftdm_running ( ) ) ;
ftdm_sleep ( 2000 ) ;
2009-04-22 21:22:42 +00:00
break ;
2010-11-06 16:08:07 +01:00
2009-04-22 21:22:42 +00:00
default :
break ;
}
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Checks flags on a pri span
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ return 0 on success , - 1 on error
*/
2009-02-07 23:14:25 +00:00
static int check_flags ( lpwrap_pri_t * spri )
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
2009-02-07 23:14:25 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ftdm_running ( ) | | ftdm_test_flag ( span , FTDM_SPAN_STOP_THREAD ) ) {
2009-03-11 02:04:18 +00:00
return - 1 ;
}
2009-04-22 21:22:42 +00:00
check_state ( span ) ;
check_events ( span ) ;
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri restart event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_restart ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
ftdm_channel_t * chan = ftdm_span_get_channel ( span , pevent - > restart . channel ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_NOTICE , " -- Restarting %d:%d \n " , ftdm_span_get_id ( span ) , pevent - > restart . channel ) ;
_ftdm_channel_set_state_force ( spri - > dchan , FTDM_CHANNEL_STATE_UP ) ;
2009-02-07 23:14:25 +00:00
2010-11-10 21:17:02 +01:00
if ( ! chan ) {
2009-02-07 23:14:25 +00:00
return 0 ;
}
if ( pevent - > restart . channel < 1 ) {
2010-11-10 21:17:02 +01:00
ftdm_set_state_all ( span , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_set_state_locked ( chan , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
}
return 0 ;
}
2010-11-08 00:43:09 +01:00
/*
* FACILITY Advice - On - Charge handler
*/
# ifdef HAVE_LIBPRI_AOC
static const char * aoc_billing_id ( const int id )
{
switch ( id ) {
case PRI_AOC_E_BILLING_ID_NOT_AVAILABLE :
return " not available " ;
case PRI_AOC_E_BILLING_ID_NORMAL :
return " normal " ;
case PRI_AOC_E_BILLING_ID_REVERSE :
return " reverse " ;
case PRI_AOC_E_BILLING_ID_CREDIT_CARD :
return " credit card " ;
case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_UNCONDITIONAL :
return " call forwarding unconditional " ;
case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_BUSY :
return " call forwarding busy " ;
case PRI_AOC_E_BILLING_ID_CALL_FORWARDING_NO_REPLY :
return " call forwarding no reply " ;
case PRI_AOC_E_BILLING_ID_CALL_DEFLECTION :
return " call deflection " ;
case PRI_AOC_E_BILLING_ID_CALL_TRANSFER :
return " call transfer " ;
default :
return " unknown \n " ;
}
}
static float aoc_money_amount ( const struct pri_aoc_amount * amount )
{
switch ( amount - > multiplier ) {
case PRI_AOC_MULTIPLIER_THOUSANDTH :
return amount - > cost * 0.001f ;
case PRI_AOC_MULTIPLIER_HUNDREDTH :
return amount - > cost * 0.01f ;
case PRI_AOC_MULTIPLIER_TENTH :
return amount - > cost * 0.1f ;
case PRI_AOC_MULTIPLIER_TEN :
return amount - > cost * 10.0f ;
case PRI_AOC_MULTIPLIER_HUNDRED :
return amount - > cost * 100.0f ;
case PRI_AOC_MULTIPLIER_THOUSAND :
return amount - > cost * 1000.0f ;
default :
return amount - > cost ;
}
}
static int handle_facility_aoc_s ( const struct pri_subcmd_aoc_s * aoc_s )
{
/* Left as an excercise to the reader */
return 0 ;
}
static int handle_facility_aoc_d ( const struct pri_subcmd_aoc_d * aoc_d )
{
/* Left as an excercise to the reader */
return 0 ;
}
static int handle_facility_aoc_e ( const struct pri_subcmd_aoc_e * aoc_e )
{
char tmp [ 1024 ] = { 0 } ;
int x = 0 , offset = 0 ;
switch ( aoc_e - > charge ) {
case PRI_AOC_DE_CHARGE_FREE :
strcat ( tmp , " \t charge-type: none \n " ) ;
offset = strlen ( tmp ) ;
break ;
case PRI_AOC_DE_CHARGE_CURRENCY :
sprintf ( tmp , " \t charge-type: money \n \t charge-amount: %.2f \n \t charge-currency: %s \n " ,
aoc_money_amount ( & aoc_e - > recorded . money . amount ) ,
aoc_e - > recorded . money . currency ) ;
offset = strlen ( tmp ) ;
break ;
case PRI_AOC_DE_CHARGE_UNITS :
strcat ( tmp , " \t charge-type: units \n " ) ;
offset = strlen ( tmp ) ;
for ( x = 0 ; x < aoc_e - > recorded . unit . num_items ; x + + ) {
sprintf ( & tmp [ offset ] , " \t charge-amount: %ld (type: %d) \n " ,
aoc_e - > recorded . unit . item [ x ] . number ,
aoc_e - > recorded . unit . item [ x ] . type ) ;
offset + = strlen ( & tmp [ offset ] ) ;
}
break ;
default :
strcat ( tmp , " \t charge-type: not available \n " ) ;
offset = strlen ( tmp ) ;
}
sprintf ( & tmp [ offset ] , " \t billing-id: %s \n " , aoc_billing_id ( aoc_e - > billing_id ) ) ;
offset + = strlen ( & tmp [ offset ] ) ;
strcat ( & tmp [ offset ] , " \t association-type: " ) ;
offset + = strlen ( & tmp [ offset ] ) ;
switch ( aoc_e - > associated . charging_type ) {
case PRI_AOC_E_CHARGING_ASSOCIATION_NOT_AVAILABLE :
strcat ( & tmp [ offset ] , " not available \n " ) ;
break ;
case PRI_AOC_E_CHARGING_ASSOCIATION_NUMBER :
sprintf ( & tmp [ offset ] , " number \n \t association-number: %s \n " , aoc_e - > associated . charge . number . str ) ;
break ;
case PRI_AOC_E_CHARGING_ASSOCIATION_ID :
sprintf ( & tmp [ offset ] , " id \n \t association-id: %d \n " , aoc_e - > associated . charge . id ) ;
break ;
default :
strcat ( & tmp [ offset ] , " unknown \n " ) ;
}
ftdm_log ( FTDM_LOG_INFO , " AOC-E: \n %s " , tmp ) ;
return 0 ;
}
/**
* \ brief Handler for libpri facility events
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
static int on_facility ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
{
2010-11-11 22:21:18 +01:00
struct pri_event_facility * pfac = & pevent - > facility ;
2010-11-08 00:43:09 +01:00
int i = 0 ;
if ( ! pevent )
return 0 ;
2010-11-11 22:17:09 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " Got a FACILITY event on span %d:%d \n " , ftdm_span_get_id ( spri - > span ) , pfac - > channel ) ;
2010-11-08 00:43:09 +01:00
if ( ! pfac - > subcmds | | pfac - > subcmds - > counter_subcmd < = 0 )
return 0 ;
for ( i = 0 ; i < pfac - > subcmds - > counter_subcmd ; i + + ) {
struct pri_subcommand * sub = & pfac - > subcmds - > subcmd [ i ] ;
int res = - 1 ;
switch ( sub - > cmd ) {
case PRI_SUBCMD_AOC_S : /* AOC-S: Start of call */
res = handle_facility_aoc_s ( & sub - > u . aoc_s ) ;
break ;
case PRI_SUBCMD_AOC_D : /* AOC-D: During call */
res = handle_facility_aoc_d ( & sub - > u . aoc_d ) ;
break ;
case PRI_SUBCMD_AOC_E : /* AOC-E: End of call */
res = handle_facility_aoc_e ( & sub - > u . aoc_e ) ;
break ;
case PRI_SUBCMD_AOC_CHARGING_REQ :
ftdm_log ( FTDM_LOG_NOTICE , " AOC Charging Request received \n " ) ;
break ;
case PRI_SUBCMD_AOC_CHARGING_REQ_RSP :
ftdm_log ( FTDM_LOG_NOTICE , " AOC Charging Request Response received [aoc_s data: %s, req: %x, resp: %x] \n " ,
sub - > u . aoc_request_response . valid_aoc_s ? " yes " : " no " ,
sub - > u . aoc_request_response . charging_request ,
sub - > u . aoc_request_response . charging_response ) ;
break ;
default :
ftdm_log ( FTDM_LOG_DEBUG , " FACILITY subcommand %d is not implemented, ignoring \n " , sub - > cmd ) ;
}
ftdm_log ( FTDM_LOG_DEBUG , " FACILITY subcommand %d handler returned %d \n " , sub - > cmd , res ) ;
}
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " Caught Event on span %d %u (%s) \n " , ftdm_span_get_id ( spri - > span ) , event_type , lpwrap_pri_event_str ( event_type ) ) ;
2010-11-08 00:43:09 +01:00
return 0 ;
}
2010-11-10 01:28:30 +01:00
# endif
2010-11-08 00:43:09 +01:00
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri dchan up event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_dchan_up ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-01-15 19:22:49 +00:00
if ( ! ftdm_test_flag ( spri , LPWRAP_PRI_READY ) ) {
2010-04-27 14:32:36 -04:00
ftdm_signaling_status_t status = FTDM_SIG_STATE_UP ;
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
2010-04-27 14:32:36 -04:00
ftdm_sigmsg_t sig ;
int i ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_INFO , " Span %d D-Channel UP! \n " , ftdm_span_get_id ( span ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_set_flag ( spri , LPWRAP_PRI_READY ) ;
2010-11-10 21:17:02 +01:00
ftdm_set_state_all ( span , FTDM_CHANNEL_STATE_RESTART ) ;
2009-02-07 23:14:25 +00:00
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_NOTICE , " %d:Signaling link status changed to %s \n " , ftdm_span_get_id ( span ) , ftdm_signaling_status2str ( status ) ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
for ( i = 1 ; i < = ftdm_span_get_chan_count ( span ) ; i + + ) {
ftdm_channel_t * chan = ftdm_span_get_channel ( span , i ) ;
2010-11-06 16:08:07 +01:00
2010-04-27 14:32:36 -04:00
memset ( & sig , 0 , sizeof ( sig ) ) ;
2010-11-10 21:17:02 +01:00
sig . span_id = ftdm_channel_get_span_id ( chan ) ;
sig . chan_id = ftdm_channel_get_id ( chan ) ;
sig . channel = chan ;
2010-04-27 14:32:36 -04:00
sig . event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED ;
2010-12-19 12:55:55 -05:00
sig . ev_data . sigstatus . status = status ;
2010-11-10 21:17:02 +01:00
ftdm_span_send_signal ( span , & sig ) ;
2010-04-27 14:32:36 -04:00
}
}
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri dchan down event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_dchan_down ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2010-11-06 16:08:07 +01:00
{
2010-01-15 19:22:49 +00:00
if ( ftdm_test_flag ( spri , LPWRAP_PRI_READY ) ) {
2010-04-27 14:32:36 -04:00
ftdm_signaling_status_t status = FTDM_SIG_STATE_DOWN ;
2010-11-10 21:17:02 +01:00
ftdm_span_t * span = spri - > span ;
2010-04-27 14:32:36 -04:00
ftdm_sigmsg_t sig ;
int i ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_INFO , " Span %d D-Channel DOWN! \n " , ftdm_span_get_id ( span ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_clear_flag ( spri , LPWRAP_PRI_READY ) ;
2010-11-10 21:17:02 +01:00
ftdm_set_state_all ( span , FTDM_CHANNEL_STATE_RESTART ) ;
2010-04-27 14:32:36 -04:00
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_NOTICE , " %d:Signaling link status changed to %s \n " , ftdm_span_get_id ( span ) , ftdm_signaling_status2str ( status ) ) ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
for ( i = 1 ; i < = ftdm_span_get_chan_count ( span ) ; i + + ) {
ftdm_channel_t * chan = ftdm_span_get_channel ( span , i ) ;
2010-11-06 16:08:07 +01:00
2010-04-27 14:32:36 -04:00
memset ( & sig , 0 , sizeof ( sig ) ) ;
2010-11-10 21:17:02 +01:00
sig . span_id = ftdm_channel_get_span_id ( chan ) ;
sig . chan_id = ftdm_channel_get_id ( chan ) ;
sig . channel = chan ;
2010-04-27 14:32:36 -04:00
sig . event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED ;
2010-12-19 12:55:55 -05:00
sig . ev_data . sigstatus . status = status ;
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
ftdm_span_send_signal ( span , & sig ) ;
2010-04-27 14:32:36 -04:00
}
2009-02-07 23:14:25 +00:00
}
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for any libpri event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_anything ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-02-07 23:14:25 +00:00
{
2010-11-16 22:50:43 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Caught Event span %d %u (%s) \n " , ftdm_span_get_id ( spri - > span ) , event_type , lpwrap_pri_event_str ( event_type ) ) ;
2011-06-09 11:15:53 -04:00
switch ( pevent - > e ) {
case PRI_EVENT_CONFIG_ERR :
{
ftdm_log ( FTDM_LOG_WARNING , " -- PRI error event: %s \n " , pevent - > err . err ) ;
}
break ;
}
2009-02-07 23:14:25 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Handler for libpri io fail event
* \ param spri Pri wrapper structure ( libpri , span , dchan )
* \ param event_type Event type ( unused )
* \ param pevent Event
* \ return 0
*/
2009-03-10 20:56:38 +00:00
static int on_io_fail ( lpwrap_pri_t * spri , lpwrap_pri_event_t event_type , pri_event * pevent )
2009-03-07 02:20:40 +00:00
{
2010-11-16 22:50:43 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " -- Caught Event span %d %u (%s) \n " , ftdm_span_get_id ( spri - > span ) , event_type , lpwrap_pri_event_str ( event_type ) ) ;
2009-03-07 02:20:40 +00:00
return 0 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Main thread function for libpri span ( monitor )
* \ param me Current thread
* \ param obj Span to run in this thread
2010-11-06 16:08:07 +01:00
*
* \ todo Move all init stuff outside of loop or into ftdm_libpri_configure_span ( )
2009-06-08 20:01:29 +00:00
*/
2010-01-15 19:22:49 +00:00
static void * ftdm_libpri_run ( ftdm_thread_t * me , void * obj )
2009-02-07 23:14:25 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_span_t * span = ( ftdm_span_t * ) obj ;
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2009-03-11 02:04:18 +00:00
int down = 0 ;
2009-04-22 21:22:42 +00:00
int got_d = 0 ;
2010-11-06 16:08:07 +01:00
int res = 0 ;
2010-01-15 19:22:49 +00:00
ftdm_set_flag ( span , FTDM_SPAN_IN_THREAD ) ;
2010-11-06 16:08:07 +01:00
while ( ftdm_running ( ) & & ! ftdm_test_flag ( span , FTDM_SPAN_STOP_THREAD ) ) {
2009-04-22 21:22:42 +00:00
if ( ! got_d ) {
2010-11-06 16:08:07 +01:00
int i , x ;
2010-11-10 21:17:02 +01:00
for ( i = 1 , x = 0 ; i < = ftdm_span_get_chan_count ( span ) ; i + + ) {
ftdm_channel_t * chan = ftdm_span_get_channel ( span , i ) ;
if ( ftdm_channel_get_type ( chan ) = = FTDM_CHAN_TYPE_DQ921 ) {
if ( ftdm_channel_open ( ftdm_span_get_id ( span ) , i , & isdn_data - > dchan ) = = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_DEBUG , " opening D-Channel #%d %d:%d \n " , x ,
ftdm_channel_get_span_id ( isdn_data - > dchan ) , ftdm_channel_get_id ( isdn_data - > dchan ) ) ;
2009-04-22 21:22:42 +00:00
got_d = 1 ;
x + + ;
break ;
2010-09-30 11:02:53 -04:00
} else {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_ERROR , " failed to open D-Channel #%d %d:%d \n " , x ,
ftdm_channel_get_span_id ( chan ) , ftdm_channel_get_id ( chan ) ) ;
2009-04-22 21:22:42 +00:00
}
2009-03-07 02:20:40 +00:00
}
}
}
2010-11-10 00:47:16 +01:00
if ( ! got_d | | ! isdn_data - > dchan ) {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Failed to get a D-Channel in span %d \n " , ftdm_span_get_id ( span ) ) ;
2010-09-30 11:02:53 -04:00
break ;
}
2009-03-07 02:20:40 +00:00
2010-11-06 16:08:07 +01:00
/* Initialize libpri trunk */
2010-11-07 15:48:39 +01:00
switch ( ftdm_span_get_trunk_type ( span ) ) {
2010-11-06 16:08:07 +01:00
case FTDM_TRUNK_E1 :
case FTDM_TRUNK_T1 :
case FTDM_TRUNK_J1 :
res = lpwrap_init_pri ( & isdn_data - > spri , span , isdn_data - > dchan ,
2010-11-10 22:42:18 +01:00
isdn_data - > dialect , isdn_data - > mode , isdn_data - > debug_mask ) ;
2010-11-06 16:08:07 +01:00
break ;
case FTDM_TRUNK_BRI :
res = lpwrap_init_bri ( & isdn_data - > spri , span , isdn_data - > dchan ,
2010-11-10 22:42:18 +01:00
isdn_data - > dialect , isdn_data - > mode , 1 , isdn_data - > debug_mask ) ;
2010-11-06 17:58:41 +01:00
# ifndef HAVE_LIBPRI_BRI
goto out ;
# endif
2010-11-06 16:08:07 +01:00
break ;
case FTDM_TRUNK_BRI_PTMP :
res = lpwrap_init_bri ( & isdn_data - > spri , span , isdn_data - > dchan ,
2010-11-10 22:42:18 +01:00
isdn_data - > dialect , isdn_data - > mode , 0 , isdn_data - > debug_mask ) ;
2010-11-06 17:58:41 +01:00
# ifndef HAVE_LIBPRI_BRI
goto out ;
# endif
2010-11-06 16:08:07 +01:00
break ;
default :
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Invalid trunk type " ) ;
goto out ;
}
2010-11-08 00:43:09 +01:00
# ifdef HAVE_LIBPRI_AOC
2010-11-08 00:57:50 +01:00
/*
* Only enable facility on trunk if really required ,
* this may help avoid problems on troublesome lines .
*/
2010-11-08 00:43:09 +01:00
if ( isdn_data - > opts & FTMOD_LIBPRI_OPT_FACILITY_AOC ) {
pri_facility_enable ( isdn_data - > spri . pri ) ;
}
# endif
2011-08-05 22:50:58 -04:00
/* Support the different switch of service status */
if ( isdn_data - > service_message_support ) {
pri_set_service_message_support ( isdn_data - > spri . pri , 1 /* True */ ) ;
}
2010-11-08 00:43:09 +01:00
2010-11-06 16:08:07 +01:00
if ( res = = 0 ) {
2009-03-07 02:20:40 +00:00
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_ANY , on_anything ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_RING , on_ring ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_RINGING , on_ringing ) ;
2010-11-16 22:50:43 +01:00
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_PROCEEDING , on_proceeding ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_PROGRESS , on_progress ) ;
2009-03-07 02:20:40 +00:00
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_ANSWER , on_answer ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_DCHAN_UP , on_dchan_up ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_DCHAN_DOWN , on_dchan_down ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_HANGUP_REQ , on_hangup ) ;
2011-05-03 13:02:01 +02:00
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_HANGUP_ACK , on_hangup ) ;
2009-03-07 02:20:40 +00:00
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_HANGUP , on_hangup ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_INFO_RECEIVED , on_info ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_RESTART , on_restart ) ;
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_IO_FAIL , on_io_fail ) ;
2010-11-10 01:28:30 +01:00
# ifdef HAVE_LIBPRI_AOC
2010-11-08 00:43:09 +01:00
LPWRAP_MAP_PRI_EVENT ( isdn_data - > spri , LPWRAP_PRI_EVENT_FACILITY , on_facility ) ;
2010-11-10 01:28:30 +01:00
# endif
2009-03-11 02:04:18 +00:00
if ( down ) {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_INFO , " PRI back up on span %d \n " , ftdm_span_get_id ( span ) ) ;
2010-01-15 19:22:49 +00:00
ftdm_set_state_all ( span , FTDM_CHANNEL_STATE_RESTART ) ;
2009-03-11 02:04:18 +00:00
down = 0 ;
}
2009-03-07 02:20:40 +00:00
isdn_data - > spri . on_loop = check_flags ;
2009-06-04 17:20:53 +00:00
2010-11-06 16:08:07 +01:00
lpwrap_run_pri ( & isdn_data - > spri ) ;
} else {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_CRIT , " PRI init failed! \n " ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " PRI init failed! " ) ;
break ;
2009-03-07 02:20:40 +00:00
}
2009-06-04 17:20:53 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ftdm_running ( ) | | ftdm_test_flag ( span , FTDM_SPAN_STOP_THREAD ) ) {
2009-03-10 20:56:38 +00:00
break ;
}
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_CRIT , " PRI down on span %d \n " , ftdm_span_get_id ( span ) ) ;
2010-09-30 02:37:57 -04:00
if ( isdn_data - > spri . dchan ) {
2010-11-10 21:17:02 +01:00
_ftdm_channel_set_state_force ( isdn_data - > spri . dchan , FTDM_CHANNEL_STATE_DOWN ) ;
2010-09-30 02:37:57 -04:00
}
2009-04-22 21:22:42 +00:00
if ( ! down ) {
2010-01-15 19:22:49 +00:00
ftdm_set_state_all ( span , FTDM_CHANNEL_STATE_RESTART ) ;
2009-04-22 21:22:42 +00:00
check_state ( span ) ;
}
2009-03-11 02:04:18 +00:00
check_state ( span ) ;
2009-04-22 21:22:42 +00:00
check_events ( span ) ;
2010-11-10 21:17:02 +01:00
down = 1 ;
2010-01-15 19:22:49 +00:00
ftdm_sleep ( 5000 ) ;
2009-03-07 02:20:40 +00:00
}
2010-11-06 16:08:07 +01:00
out :
2011-09-01 01:45:06 +02:00
/* close d-channel, if set */
if ( isdn_data - > dchan ) {
if ( ftdm_channel_close ( & isdn_data - > dchan ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " Failed to close D-Channel %d:%d \n " ,
ftdm_channel_get_span_id ( isdn_data - > dchan ) , ftdm_channel_get_id ( isdn_data - > dchan ) ) ;
}
}
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_DEBUG , " PRI thread ended on span %d \n " , ftdm_span_get_id ( span ) ) ;
2009-03-11 02:04:18 +00:00
2010-01-15 19:22:49 +00:00
ftdm_clear_flag ( span , FTDM_SPAN_IN_THREAD ) ;
ftdm_clear_flag ( isdn_data , FTMOD_LIBPRI_RUNNING ) ;
2009-03-11 02:04:18 +00:00
2009-02-07 23:14:25 +00:00
return NULL ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Stops a libpri span
* \ param span Span to halt
* \ return Success
*
* Sets a stop flag and waits for the thread to end
*/
2010-01-15 19:22:49 +00:00
static ftdm_status_t ftdm_libpri_stop ( ftdm_span_t * span )
2009-03-10 20:56:38 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2009-03-11 02:04:18 +00:00
2010-01-15 19:22:49 +00:00
if ( ! ftdm_test_flag ( isdn_data , FTMOD_LIBPRI_RUNNING ) ) {
return FTDM_FAIL ;
2009-03-11 02:04:18 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_set_state_all ( span , FTDM_CHANNEL_STATE_RESTART ) ;
2010-11-06 16:08:07 +01:00
2009-03-11 02:04:18 +00:00
check_state ( span ) ;
2010-11-06 16:08:07 +01:00
2010-01-15 19:22:49 +00:00
ftdm_set_flag ( span , FTDM_SPAN_STOP_THREAD ) ;
2010-11-06 16:08:07 +01:00
while ( ftdm_test_flag ( span , FTDM_SPAN_IN_THREAD ) ) {
2010-01-15 19:22:49 +00:00
ftdm_sleep ( 100 ) ;
2009-03-10 20:56:38 +00:00
}
2010-11-06 16:08:07 +01:00
2009-03-11 02:04:18 +00:00
check_state ( span ) ;
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2009-03-10 20:56:38 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Starts a libpri span
* \ param span Span to halt
* \ return Success or failure
*
* Launches a thread to monitor the span
*/
2010-01-15 19:22:49 +00:00
static ftdm_status_t ftdm_libpri_start ( ftdm_span_t * span )
2009-02-07 23:14:25 +00:00
{
2010-01-15 19:22:49 +00:00
ftdm_libpri_data_t * isdn_data = span - > signal_data ;
2009-02-07 23:14:25 +00:00
2010-01-15 19:22:49 +00:00
if ( ftdm_test_flag ( isdn_data , FTMOD_LIBPRI_RUNNING ) ) {
return FTDM_FAIL ;
2009-03-11 02:04:18 +00:00
}
2010-01-15 19:22:49 +00:00
ftdm_clear_flag ( span , FTDM_SPAN_STOP_THREAD ) ;
ftdm_clear_flag ( span , FTDM_SPAN_IN_THREAD ) ;
2009-03-11 02:04:18 +00:00
2010-01-15 19:22:49 +00:00
ftdm_set_flag ( isdn_data , FTMOD_LIBPRI_RUNNING ) ;
2009-03-07 02:20:40 +00:00
2010-11-10 22:42:18 +01:00
return ftdm_thread_create_detached ( ftdm_libpri_run , span ) ;
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Converts a node string to node value
* \ param node Node string to convert
* \ return - 1 on failure , node value on success
*/
2010-11-10 22:42:18 +01:00
static int parse_mode ( const char * mode )
2009-02-07 23:14:25 +00:00
{
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( mode , " cpe " ) | | ! strcasecmp ( mode , " user " ) )
2009-02-07 23:14:25 +00:00
return PRI_CPE ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( mode , " network " ) | | ! strcasecmp ( mode , " net " ) )
2009-02-07 23:14:25 +00:00
return PRI_NETWORK ;
2010-11-10 22:42:18 +01:00
2009-03-01 23:10:17 +00:00
return - 1 ;
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Converts a switch string to switch value
* \ param swtype Swtype string to convert
* \ return Switch value
*/
2010-11-10 22:42:18 +01:00
static int parse_dialect ( const char * dialect )
2009-02-07 23:14:25 +00:00
{
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " ni1 " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_NI1 ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " ni2 " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_NI2 ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " dms100 " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_DMS100 ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " lucent5e " ) | | ! strcasecmp ( dialect , " 5ess " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_LUCENT5E ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " att4ess " ) | | ! strcasecmp ( dialect , " 4ess " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_ATT4ESS ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " euroisdn " ) | | ! strcasecmp ( dialect , " q931 " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_EUROISDN_E1 ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " gr303eoc " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_GR303_EOC ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( dialect , " gr303tmc " ) )
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_GR303_TMC ;
2010-11-06 16:08:07 +01:00
2009-02-07 23:14:25 +00:00
return PRI_SWITCH_DMS100 ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Converts a L1 string to L1 value
* \ param l1 L1 string to convert
* \ return L1 value
*/
2010-11-10 22:42:18 +01:00
static int parse_layer1 ( const char * val )
2009-02-07 23:14:25 +00:00
{
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( val , " alaw " ) )
2009-02-07 23:14:25 +00:00
return PRI_LAYER_1_ALAW ;
2010-11-06 16:08:07 +01:00
2009-02-07 23:14:25 +00:00
return PRI_LAYER_1_ULAW ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Converts a DP string to DP value
* \ param dp DP string to convert
* \ return DP value
*/
2010-11-10 22:42:18 +01:00
static int parse_ton ( const char * ton )
2009-02-07 23:14:25 +00:00
{
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( ton , " international " ) )
2009-02-07 23:14:25 +00:00
return PRI_INTERNATIONAL_ISDN ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( ton , " national " ) )
2009-02-07 23:14:25 +00:00
return PRI_NATIONAL_ISDN ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( ton , " local " ) )
2009-02-07 23:14:25 +00:00
return PRI_LOCAL_ISDN ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( ton , " private " ) )
2009-02-07 23:14:25 +00:00
return PRI_PRIVATE ;
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( ton , " unknown " ) )
2009-02-07 23:14:25 +00:00
return PRI_UNKNOWN ;
return PRI_UNKNOWN ;
}
2011-06-29 13:26:51 +02:00
/**
* \ brief Parse overlap string to value
* \ param val String to parse
* \ return Overlap flags
*/
static int parse_overlap_dial ( const char * val )
{
if ( ! strcasecmp ( val , " yes " ) | | ! strcasecmp ( val , " both " ) )
return FTMOD_LIBPRI_OVERLAP_BOTH ;
if ( ! strcasecmp ( val , " incoming " ) | | ! strcasecmp ( val , " receive " ) )
return FTMOD_LIBPRI_OVERLAP_RECEIVE ;
if ( ! strcasecmp ( val , " outgoing " ) | | ! strcasecmp ( val , " send " ) )
return FTMOD_LIBPRI_OVERLAP_SEND ;
if ( ! strcasecmp ( val , " no " ) )
return FTMOD_LIBPRI_OVERLAP_NONE ;
return - 1 ;
}
2010-11-06 16:08:07 +01:00
/**
* \ brief Parses an option string to flags
* \ param in String to parse for configuration options
* \ return Flags
*/
static uint32_t parse_opts ( const char * in )
{
uint32_t flags = 0 ;
if ( ! in ) {
return 0 ;
}
if ( strstr ( in , " suggest_channel " ) ) {
flags | = FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL ;
}
if ( strstr ( in , " omit_display " ) ) {
flags | = FTMOD_LIBPRI_OPT_OMIT_DISPLAY_IE ;
}
if ( strstr ( in , " omit_redirecting_number " ) ) {
flags | = FTMOD_LIBPRI_OPT_OMIT_REDIRECTING_NUMBER_IE ;
}
2010-11-08 00:43:09 +01:00
if ( strstr ( in , " aoc " ) ) {
flags | = FTMOD_LIBPRI_OPT_FACILITY_AOC ;
}
2010-11-06 16:08:07 +01:00
return flags ;
}
2009-06-08 20:01:29 +00:00
/**
* \ brief Initialises a libpri span from configuration variables
* \ param span Span to configure
* \ param sig_cb Callback function for event signals
2010-11-07 17:00:54 +01:00
* \ param ftdm_parameters List of configuration variables
2009-06-08 20:01:29 +00:00
* \ return Success or failure
*/
2010-11-07 17:00:54 +01:00
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION ( ftdm_libpri_configure_span )
2009-02-07 23:14:25 +00:00
{
2010-11-11 00:16:25 +01:00
ftdm_libpri_data_t * isdn_data = NULL ;
//ftdm_channel_t *dchan = NULL;
2010-11-10 21:17:02 +01:00
uint32_t bchan_count = 0 ;
uint32_t dchan_count = 0 ;
2010-11-11 00:16:25 +01:00
uint32_t i ;
2009-03-19 20:15:39 +00:00
2010-11-07 15:48:39 +01:00
if ( ftdm_span_get_trunk_type ( span ) > = FTDM_TRUNK_NONE ) {
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_WARNING , " Invalid trunk type '%s' defaulting to T1. \n " , ftdm_span_get_trunk_type_str ( span ) ) ;
2010-11-07 15:48:39 +01:00
ftdm_span_set_trunk_type ( span , FTDM_TRUNK_T1 ) ;
2009-02-07 23:14:25 +00:00
}
2010-11-06 16:08:07 +01:00
2010-11-10 21:17:02 +01:00
for ( i = 1 ; i < = ftdm_span_get_chan_count ( span ) ; i + + ) {
ftdm_channel_t * chan = ftdm_span_get_channel ( span , i ) ;
switch ( ftdm_channel_get_type ( chan ) ) {
case FTDM_CHAN_TYPE_DQ921 :
if ( dchan_count > 1 ) {
ftdm_log ( FTDM_LOG_ERROR , " Span has more than 2 D-Channels! \n " ) ;
2009-02-07 23:14:25 +00:00
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Span has more than 2 D-Channels! " ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2009-02-07 23:14:25 +00:00
} else {
2009-03-07 02:20:40 +00:00
#if 0
2010-11-10 21:17:02 +01:00
if ( ftdm_channel_open ( ftdm_span_get_id ( span ) , i , & dchan ) = = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_DEBUG , " opening D-Channel %d:%d \n " , ftdm_channel_get_span_id ( dchan ) , ftdm_channel_get_id ( dchan ) ) ;
_ftdm_channel_set_state_force ( dchan , FTDM_CHANNEL_STATE_UP ) ;
} else {
ftdm_log ( FTDM_LOG_ERROR , " Failed to open D-Channel %d:%d \n " , ftdm_channel_get_span_id ( chan ) , ftdm_channel_getid ( chan ) ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Failed to open D-Channel %d:%d \n " , ftdm_channel_get_span_id ( chan ) , ftdm_channel_getid ( chan ) ) ;
return FTDM_FAIL ;
2009-02-07 23:14:25 +00:00
}
2009-03-07 02:20:40 +00:00
# endif
2010-11-10 21:17:02 +01:00
dchan_count + + ;
2009-02-07 23:14:25 +00:00
}
2010-11-10 21:17:02 +01:00
break ;
case FTDM_CHAN_TYPE_B :
bchan_count + + ;
break ;
default : /* Ignore other channel types */
break ;
2009-02-07 23:14:25 +00:00
}
}
2010-11-10 21:17:02 +01:00
if ( ! dchan_count ) {
2010-11-10 00:47:16 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Span has no D-Channel! \n " ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Span has no D-Channel! " ) ;
2010-01-15 19:22:49 +00:00
return FTDM_FAIL ;
2009-02-07 23:14:25 +00:00
}
2010-11-10 21:17:02 +01:00
if ( ! bchan_count ) {
ftdm_log ( FTDM_LOG_ERROR , " Span has no B-Channels! \n " ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Span has no B-Channels! " ) ;
return FTDM_FAIL ;
}
2009-02-07 23:14:25 +00:00
2010-01-15 19:22:49 +00:00
isdn_data = ftdm_malloc ( sizeof ( * isdn_data ) ) ;
2009-02-07 23:14:25 +00:00
assert ( isdn_data ! = NULL ) ;
memset ( isdn_data , 0 , sizeof ( * isdn_data ) ) ;
2009-09-29 22:29:35 +00:00
2011-05-10 19:35:56 +02:00
/* set some default values */
isdn_data - > ton = PRI_UNKNOWN ;
2012-07-11 19:15:35 +02:00
/* Use span's trunk_mode as a reference for the default libpri mode */
if ( ftdm_span_get_trunk_mode ( span ) = = FTDM_TRUNK_MODE_NET ) {
isdn_data - > mode = PRI_NETWORK ;
} else {
isdn_data - > mode = PRI_CPE ;
}
2010-11-07 15:48:39 +01:00
switch ( ftdm_span_get_trunk_type ( span ) ) {
case FTDM_TRUNK_BRI :
case FTDM_TRUNK_BRI_PTMP :
2010-11-09 15:51:30 +01:00
# ifndef HAVE_LIBPRI_BRI
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Unsupported trunk type: '%s', libpri too old \n " , ftdm_span_get_trunk_type_str ( span ) ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Unsupported trunk type [%s], libpri too old " , ftdm_span_get_trunk_type_str ( span ) ) ;
2012-06-26 21:33:40 +02:00
goto error ;
2010-11-09 15:51:30 +01:00
# endif
case FTDM_TRUNK_E1 :
2010-11-07 15:48:39 +01:00
ftdm_log ( FTDM_LOG_NOTICE , " Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk \n " ) ;
2011-05-10 19:35:56 +02:00
isdn_data - > layer1 = PRI_LAYER_1_ALAW ;
isdn_data - > dialect = PRI_SWITCH_EUROISDN_E1 ;
2010-11-07 15:48:39 +01:00
break ;
case FTDM_TRUNK_T1 :
case FTDM_TRUNK_J1 :
ftdm_log ( FTDM_LOG_NOTICE , " Setting default Layer 1 to ULAW since this is a T1/J1 trunk \n " ) ;
2011-05-10 19:35:56 +02:00
isdn_data - > layer1 = PRI_LAYER_1_ULAW ;
isdn_data - > dialect = PRI_SWITCH_LUCENT5E ;
2010-11-07 15:48:39 +01:00
break ;
default :
2010-11-10 21:17:02 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Invalid trunk type: '%s' \n " , ftdm_span_get_trunk_type_str ( span ) ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Invalid trunk type [%s] " , ftdm_span_get_trunk_type_str ( span ) ) ;
2012-06-26 21:33:40 +02:00
goto error ;
}
/*
* Init MSN filter
*/
if ( msn_filter_init ( isdn_data ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " Failed to init MSN filter \n " ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Failed to init MSN filter " ) ;
goto error ;
2010-11-06 16:08:07 +01:00
}
2010-11-15 12:33:58 +01:00
for ( i = 0 ; ftdm_parameters [ i ] . var ; i + + ) {
2010-11-11 00:16:25 +01:00
const char * var = ftdm_parameters [ i ] . var ;
const char * val = ftdm_parameters [ i ] . val ;
2010-11-06 16:08:07 +01:00
2010-11-15 12:33:58 +01:00
if ( ftdm_strlen_zero ( var ) ) {
ftdm_log ( FTDM_LOG_WARNING , " Skipping parameter with no name \n " ) ;
continue ;
}
if ( ftdm_strlen_zero ( val ) ) {
2010-11-06 16:08:07 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Parameter '%s' has no value \n " , var ) ;
2010-11-07 19:55:00 +01:00
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Parameter [%s] has no value " , var ) ;
2012-06-26 21:33:40 +02:00
goto error ;
2010-11-06 16:08:07 +01:00
}
2010-11-10 22:42:18 +01:00
if ( ! strcasecmp ( var , " node " ) | | ! strcasecmp ( var , " mode " ) ) {
if ( ( isdn_data - > mode = parse_mode ( val ) ) = = - 1 ) {
2012-07-11 19:15:35 +02:00
ftdm_log ( FTDM_LOG_ERROR , " Unknown node type '%s' \n " , val ) ;
goto error ;
2009-02-07 23:14:25 +00:00
}
2010-11-06 16:08:07 +01:00
}
2010-11-10 22:42:18 +01:00
else if ( ! strcasecmp ( var , " switch " ) | | ! strcasecmp ( var , " dialect " ) ) {
isdn_data - > dialect = parse_dialect ( val ) ;
2010-11-06 16:08:07 +01:00
}
else if ( ! strcasecmp ( var , " opts " ) ) {
2009-03-19 20:15:39 +00:00
isdn_data - > opts = parse_opts ( val ) ;
2010-11-06 16:08:07 +01:00
}
2010-11-10 22:42:18 +01:00
else if ( ! strcasecmp ( var , " dp " ) | | ! strcasecmp ( var , " ton " ) ) {
isdn_data - > ton = parse_ton ( val ) ;
2010-11-06 16:08:07 +01:00
}
2010-11-10 22:42:18 +01:00
else if ( ! strcasecmp ( var , " l1 " ) | | ! strcasecmp ( var , " layer1 " ) ) {
isdn_data - > layer1 = parse_layer1 ( val ) ;
2010-11-06 16:08:07 +01:00
}
2011-06-29 13:26:51 +02:00
else if ( ! strcasecmp ( var , " overlapdial " ) ) {
if ( ( isdn_data - > overlap = parse_overlap_dial ( val ) ) = = - 1 ) {
ftdm_log ( FTDM_LOG_ERROR , " Invalid overlap flag, ignoring parameter \n " ) ;
isdn_data - > overlap = FTMOD_LIBPRI_OVERLAP_NONE ;
}
}
2010-11-06 16:08:07 +01:00
else if ( ! strcasecmp ( var , " debug " ) ) {
2010-11-10 22:42:18 +01:00
if ( parse_debug ( val , & isdn_data - > debug_mask ) = = - 1 ) {
2010-11-07 15:48:39 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Invalid debug flag, ignoring parameter \n " ) ;
2010-11-10 22:42:18 +01:00
isdn_data - > debug_mask = 0 ;
2010-11-07 15:48:39 +01:00
}
2010-11-06 16:08:07 +01:00
}
2011-08-05 22:50:58 -04:00
else if ( ! strcasecmp ( var , " service_message_support " ) ) {
if ( ftdm_true ( val ) ) {
isdn_data - > service_message_support = 1 ;
}
}
2012-06-26 21:33:40 +02:00
else if ( ! strcasecmp ( var , " local-number " ) | | ! strcasecmp ( var , " msn " ) ) {
if ( msn_filter_add ( isdn_data , val ) ! = FTDM_SUCCESS ) {
ftdm_log ( FTDM_LOG_ERROR , " Invalid MSN/DDI(s) '%s' specified \n " , val ) ;
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Invalid MSN/DDI(s) '%s' specified! " , val ) ;
goto error ;
}
}
2010-11-06 16:08:07 +01:00
else {
2010-11-07 19:55:00 +01:00
ftdm_log ( FTDM_LOG_ERROR , " Unknown parameter '%s', aborting configuration \n " , var ) ;
2009-02-07 23:14:25 +00:00
snprintf ( span - > last_error , sizeof ( span - > last_error ) , " Unknown parameter [%s] " , var ) ;
2012-06-26 21:33:40 +02:00
goto error ;
2009-02-07 23:14:25 +00:00
}
}
2010-11-06 16:08:07 +01:00
2012-07-11 19:15:35 +02:00
/* Check if modes match and log a message if they do not. Just to be on the safe side. */
if ( isdn_data - > mode = = PRI_CPE & & ftdm_span_get_trunk_mode ( span ) = = FTDM_TRUNK_MODE_NET ) {
ftdm_log ( FTDM_LOG_WARNING , " Span '%s' signalling set up for TE/CPE/USER mode, while port is running in NT/NET mode. You may want to check your 'trunk_mode' settings. \n " ,
ftdm_span_get_name ( span ) ) ;
}
else if ( isdn_data - > mode = = PRI_NETWORK & & ftdm_span_get_trunk_mode ( span ) = = FTDM_TRUNK_MODE_CPE ) {
ftdm_log ( FTDM_LOG_WARNING , " Span '%s' signalling set up for NT/NET mode, while port is running in TE/CPE/USER mode. You may want to check your 'trunk_mode' settings. \n " ,
ftdm_span_get_name ( span ) ) ;
}
2010-01-15 19:22:49 +00:00
span - > start = ftdm_libpri_start ;
2010-11-06 16:08:07 +01:00
span - > stop = ftdm_libpri_stop ;
2010-02-09 22:01:15 +00:00
span - > signal_cb = sig_cb ;
2009-02-07 23:14:25 +00:00
span - > signal_data = isdn_data ;
2010-01-15 19:22:49 +00:00
span - > signal_type = FTDM_SIGTYPE_ISDN ;
2009-02-07 23:14:25 +00:00
span - > outgoing_call = isdn_outgoing_call ;
2010-11-06 16:08:07 +01:00
span - > state_map = & isdn_state_map ;
2010-12-31 13:44:20 -05:00
span - > state_processor = state_advance ;
2010-11-06 16:08:07 +01:00
2010-04-27 14:32:36 -04:00
span - > get_channel_sig_status = isdn_get_channel_sig_status ;
span - > get_span_sig_status = isdn_get_span_sig_status ;
2010-11-06 16:08:07 +01:00
2011-01-13 23:09:51 +01:00
/* move calls to PROCEED state when they hit dialplan (ROUTING state in FreeSWITCH) */
ftdm_set_flag ( span , FTDM_SPAN_USE_PROCEED_STATE ) ;
2010-01-15 19:22:49 +00:00
if ( ( isdn_data - > opts & FTMOD_LIBPRI_OPT_SUGGEST_CHANNEL ) ) {
2009-02-07 23:14:25 +00:00
span - > channel_request = isdn_channel_request ;
2010-04-05 16:01:08 -04:00
ftdm_set_flag ( span , FTDM_SPAN_SUGGEST_CHAN_ID ) ;
2009-02-07 23:14:25 +00:00
}
2010-01-15 19:22:49 +00:00
return FTDM_SUCCESS ;
2012-06-26 21:33:40 +02:00
error :
msn_filter_destroy ( isdn_data ) ;
ftdm_safe_free ( isdn_data ) ;
return FTDM_FAIL ;
2009-02-07 23:14:25 +00:00
}
2009-06-08 20:01:29 +00:00
/**
2010-01-15 20:08:43 +00:00
* \ brief FreeTDM libpri signaling and IO module definition
2009-06-08 20:01:29 +00:00
*/
2010-11-06 16:08:07 +01:00
ftdm_module_t ftdm_module = {
2009-02-07 23:14:25 +00:00
" libpri " ,
2010-01-15 19:22:49 +00:00
ftdm_libpri_io_init ,
ftdm_libpri_unload ,
ftdm_libpri_init ,
2010-11-07 17:00:54 +01:00
NULL ,
NULL ,
ftdm_libpri_configure_span
2009-02-07 23:14:25 +00:00
} ;
/* For Emacs:
* Local Variables :
* mode : c
* indent - tabs - mode : t
* tab - width : 4
* c - basic - offset : 4
* End :
* For VIM :
2009-09-14 22:06:20 +00:00
* vim : set softtabstop = 4 shiftwidth = 4 tabstop = 4 :
2009-02-07 23:14:25 +00:00
*/