@ -133,8 +133,11 @@
# define MAXDTMF 32
# define MAXDTMF 32
# define MAXMACRO 2048
# define MAXMACRO 2048
# define MAXGOSUB 2048
# define MACROTIME 100
# define MACROTIME 100
# define GOSUBTIME 100
# define MACROPTIME 500
# define MACROPTIME 500
# define GOSUBPTIME 500
# define DTMF_TIMEOUT 3
# define DTMF_TIMEOUT 3
# ifdef __RPT_NOTCH
# ifdef __RPT_NOTCH
@ -157,6 +160,7 @@
# define NODES "nodes"
# define NODES "nodes"
# define MEMORY "memory"
# define MEMORY "memory"
# define MACRO "macro"
# define MACRO "macro"
# define GOSUB "gosub"
# define FUNCTIONS "functions"
# define FUNCTIONS "functions"
# define TELEMETRY "telemetry"
# define TELEMETRY "telemetry"
# define MORSE "morse"
# define MORSE "morse"
@ -183,7 +187,7 @@ enum {REM_OFF, REM_MONITOR, REM_TX};
enum { ID , PROC , TERM , COMPLETE , UNKEY , REMDISC , REMALREADY , REMNOTFOUND , REMGO ,
enum { ID , PROC , TERM , COMPLETE , UNKEY , REMDISC , REMALREADY , REMNOTFOUND , REMGO ,
CONNECTED , CONNFAIL , STATUS , TIMEOUT , ID1 , STATS_TIME ,
CONNECTED , CONNFAIL , STATUS , TIMEOUT , ID1 , STATS_TIME ,
STATS_VERSION , IDTALKOVER , ARB_ALPHA , TEST_TONE , REV_PATCH ,
STATS_VERSION , IDTALKOVER , ARB_ALPHA , TEST_TONE , REV_PATCH ,
TAILMSG , MACRO_NOTFOUND , MACRO_BUSY, LASTNODEKEY } ;
TAILMSG , MACRO_NOTFOUND , GOSUB_NOTFOUND, MACRO_BUSY, GOSUB _BUSY, LASTNODEKEY } ;
enum { REM_SIMPLEX , REM_MINUS , REM_PLUS } ;
enum { REM_SIMPLEX , REM_MINUS , REM_PLUS } ;
@ -418,7 +422,9 @@ static struct rpt
) ;
) ;
char memory [ 80 ] ;
char memory [ 80 ] ;
char macro [ 80 ] ;
char macro [ 80 ] ;
char gosub [ 80 ] ;
char startupmacro [ 80 ] ;
char startupmacro [ 80 ] ;
char startupgosub [ 80 ] ;
int iobase ;
int iobase ;
char funcchar ;
char funcchar ;
char endchar ;
char endchar ;
@ -437,6 +443,7 @@ static struct rpt
char enable ;
char enable ;
char dtmfbuf [ MAXDTMF ] ;
char dtmfbuf [ MAXDTMF ] ;
char macrobuf [ MAXMACRO ] ;
char macrobuf [ MAXMACRO ] ;
char gosubbuf [ MAXGOSUB ] ;
char rem_dtmfbuf [ MAXDTMF ] ;
char rem_dtmfbuf [ MAXDTMF ] ;
char lastdtmfcommand [ MAXDTMF ] ;
char lastdtmfcommand [ MAXDTMF ] ;
char cmdnode [ 50 ] ;
char cmdnode [ 50 ] ;
@ -474,6 +481,7 @@ static struct rpt
char patchcontext [ MAXPATCHCONTEXT ] ;
char patchcontext [ MAXPATCHCONTEXT ] ;
int patchdialtime ;
int patchdialtime ;
int macro_longest ;
int macro_longest ;
int gosub_longest ;
int phone_longestfunc ;
int phone_longestfunc ;
int dphone_longestfunc ;
int dphone_longestfunc ;
int link_longestfunc ;
int link_longestfunc ;
@ -484,6 +492,7 @@ static struct rpt
time_t disgorgetime ;
time_t disgorgetime ;
time_t lastthreadrestarttime ;
time_t lastthreadrestarttime ;
long macrotimer ;
long macrotimer ;
long gosubtimer ;
char lastnodewhichkeyedusup [ MAXNODESTR ] ;
char lastnodewhichkeyedusup [ MAXNODESTR ] ;
# ifdef __RPT_NOTCH
# ifdef __RPT_NOTCH
struct rptfilter
struct rptfilter
@ -784,6 +793,7 @@ static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int c
static int function_cop ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
static int function_cop ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
static int function_remote ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
static int function_remote ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
static int function_macro ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
static int function_macro ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
static int function_gosub ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink ) ;
/*
/*
* Function table
* Function table
*/
*/
@ -796,6 +806,7 @@ static struct function_table_tag function_table[] = {
{ " status " , function_status } ,
{ " status " , function_status } ,
{ " remote " , function_remote } ,
{ " remote " , function_remote } ,
{ " macro " , function_macro }
{ " macro " , function_macro }
{ " gosub " , function_gosub }
} ;
} ;
/*
/*
@ -955,6 +966,7 @@ static void load_rpt_vars(int n, int init)
rpt_vars [ n ] . p . politeid = POLITEID ;
rpt_vars [ n ] . p . politeid = POLITEID ;
ast_copy_string ( rpt_vars [ n ] . p . memory , MEMORY , sizeof ( rpt_vars [ n ] . p . memory ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . memory , MEMORY , sizeof ( rpt_vars [ n ] . p . memory ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . macro , MACRO , sizeof ( rpt_vars [ n ] . p . macro ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . macro , MACRO , sizeof ( rpt_vars [ n ] . p . macro ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . gosub , GOSUB , sizeof ( rpt_vars [ n ] . p . gosub ) ) ;
rpt_vars [ n ] . p . iobase = DEFAULT_IOBASE ;
rpt_vars [ n ] . p . iobase = DEFAULT_IOBASE ;
ast_copy_string ( rpt_vars [ n ] . p . functions , FUNCTIONS , sizeof ( rpt_vars [ n ] . p . functions ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . functions , FUNCTIONS , sizeof ( rpt_vars [ n ] . p . functions ) ) ;
rpt_vars [ n ] . p . simple = 1 ;
rpt_vars [ n ] . p . simple = 1 ;
@ -1014,8 +1026,12 @@ static void load_rpt_vars(int n, int init)
ast_copy_string ( rpt_vars [ n ] . p . memory , var - > value , sizeof ( rpt_vars [ n ] . p . memory ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . memory , var - > value , sizeof ( rpt_vars [ n ] . p . memory ) ) ;
} else if ( ! strcmp ( var - > name , " macro " ) ) {
} else if ( ! strcmp ( var - > name , " macro " ) ) {
ast_copy_string ( rpt_vars [ n ] . p . macro , var - > value , sizeof ( rpt_vars [ n ] . p . macro ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . macro , var - > value , sizeof ( rpt_vars [ n ] . p . macro ) ) ;
} else if ( ! strcmp ( var - > name , " gosub " ) ) {
ast_copy_string ( rpt_vars [ n ] . p . gosub , var - > value , sizeof ( rpt_vars [ n ] . p . gosub ) ) ;
} else if ( ! strcmp ( var - > name , " startup_macro " ) ) {
} else if ( ! strcmp ( var - > name , " startup_macro " ) ) {
ast_copy_string ( rpt_vars [ n ] . p . startupmacro , var - > value , sizeof ( rpt_vars [ n ] . p . startupmacro ) ) ;
ast_copy_string ( rpt_vars [ n ] . p . startupmacro , var - > value , sizeof ( rpt_vars [ n ] . p . startupmacro ) ) ;
} else if ( ! strcmp ( var - > name , " startup_gosub " ) ) {
ast_copy_string ( rpt_vars [ n ] . p . startupgosub , var - > value , sizeof ( rpt_vars [ n ] . p . startupgosub ) ) ;
} else if ( ! strcmp ( var - > name , " iobase " ) ) {
} else if ( ! strcmp ( var - > name , " iobase " ) ) {
/* do not use atoi() here, we need to be able to have
/* do not use atoi() here, we need to be able to have
the input specified in hex or decimal so we use
the input specified in hex or decimal so we use
@ -1101,6 +1117,12 @@ static void load_rpt_vars(int n, int init)
if ( ( j = strlen ( vp - > name ) ) > rpt_vars [ n ] . macro_longest )
if ( ( j = strlen ( vp - > name ) ) > rpt_vars [ n ] . macro_longest )
rpt_vars [ n ] . macro_longest = j ;
rpt_vars [ n ] . macro_longest = j ;
}
}
rpt_vars [ n ] . gosub_longest = 1 ;
for ( vp = ast_variable_browse ( cfg , rpt_vars [ n ] . p . gosub ) ; vp ; vp = vp - > next ) {
if ( ( j = strlen ( vp - > name ) ) > rpt_vars [ n ] . gosub_longest )
rpt_vars [ n ] . gosub_longest = j ;
}
ast_mutex_unlock ( & rpt_vars [ n ] . lock ) ;
ast_mutex_unlock ( & rpt_vars [ n ] . lock ) ;
}
}
@ -1961,11 +1983,21 @@ static void *rpt_tele_thread(void *this)
wait_interval ( myrpt , DLY_TELEM , mychannel ) ;
wait_interval ( myrpt , DLY_TELEM , mychannel ) ;
res = ast_streamfile ( mychannel , " rpt/macro_notfound " , mychannel - > language ) ;
res = ast_streamfile ( mychannel , " rpt/macro_notfound " , mychannel - > language ) ;
break ;
break ;
case GOSUB_NOTFOUND :
/* wait a little bit */
wait_interval ( myrpt , DLY_TELEM , mychannel ) ;
res = ast_streamfile ( mychannel , " rpt/gosub_notfound " , mychannel - > language ) ;
break ;
case MACRO_BUSY :
case MACRO_BUSY :
/* wait a little bit */
/* wait a little bit */
wait_interval ( myrpt , DLY_TELEM , mychannel ) ;
wait_interval ( myrpt , DLY_TELEM , mychannel ) ;
res = ast_streamfile ( mychannel , " rpt/macro_busy " , mychannel - > language ) ;
res = ast_streamfile ( mychannel , " rpt/macro_busy " , mychannel - > language ) ;
break ;
break ;
case GOSUB_BUSY :
/* wait a little bit */
wait_interval ( myrpt , DLY_TELEM , mychannel ) ;
res = ast_streamfile ( mychannel , " rpt/gosub_busy " , mychannel - > language ) ;
break ;
case UNKEY :
case UNKEY :
if ( myrpt - > patchnoct & & myrpt - > callmode ) { /* If no CT during patch configured, then don't send one */
if ( myrpt - > patchnoct & & myrpt - > callmode ) { /* If no CT during patch configured, then don't send one */
imdone = 1 ;
imdone = 1 ;
@ -3283,6 +3315,54 @@ static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int co
return DC_COMPLETE ;
return DC_COMPLETE ;
}
}
/*
* Gosub
*/
static int function_gosub ( struct rpt * myrpt , char * param , char * digitbuf , int command_source , struct rpt_link * mylink )
{
const char * val ;
int i ;
struct ast_channel * mychannel ;
if ( ( ! myrpt - > remote ) & & ( ! myrpt - > enable ) )
return DC_ERROR ;
if ( debug )
ast_log ( LOG_DEBUG , " @@@@ gosub param = %s, digitbuf = %s \n " , ( param ) ? param : " (null) " , digitbuf ) ;
mychannel = myrpt - > remchannel ;
if ( ast_strlen_zero ( digitbuf ) ) /* needs 1 digit */
return DC_INDETERMINATE ;
for ( i = 0 ; i < digitbuf [ i ] ; i + + ) {
if ( ( digitbuf [ i ] < ' 0 ' ) | | ( digitbuf [ i ] > ' 9 ' ) )
return DC_ERROR ;
}
if ( * digitbuf = = ' 0 ' )
val = myrpt - > p . startupgosub ;
else
val = ast_variable_retrieve ( myrpt - > cfg , myrpt - > p . gosub , digitbuf ) ;
/* param was 1 for local buf */
if ( ! val ) {
rpt_telemetry ( myrpt , GOSUB_NOTFOUND , NULL ) ;
return DC_COMPLETE ;
}
rpt_mutex_lock ( & myrpt - > lock ) ;
if ( ( sizeof ( myrpt - > gosubbuf ) - strlen ( myrpt - > gosubbuf ) ) < strlen ( val ) ) {
rpt_mutex_unlock ( & myrpt - > lock ) ;
rpt_telemetry ( myrpt , GOSUB_BUSY , NULL ) ;
return DC_ERROR ;
}
myrpt - > gosubtimer = GOSUBTIME ;
strncat ( myrpt - > gosubbuf , val , sizeof ( myrpt - > gosubbuf ) - 1 ) ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
return DC_COMPLETE ;
}
/*
/*
* COP - Control operator
* COP - Control operator
*/
*/
@ -5798,6 +5878,9 @@ static void *rpt(void *this)
if ( myrpt - > p . startupmacro ) {
if ( myrpt - > p . startupmacro ) {
snprintf ( myrpt - > macrobuf , sizeof ( myrpt - > macrobuf ) , " PPPP%s " , myrpt - > p . startupmacro ) ;
snprintf ( myrpt - > macrobuf , sizeof ( myrpt - > macrobuf ) , " PPPP%s " , myrpt - > p . startupmacro ) ;
}
}
if ( myrpt - > p . startupgosub ) {
snprintf ( myrpt - > gosubbuf , sizeof ( myrpt - > gosubbuf ) , " PPPP%s " , myrpt - > p . startupgosub ) ;
}
rpt_mutex_unlock ( & myrpt - > lock ) ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
val = 0 ;
val = 0 ;
ast_channel_setoption ( myrpt - > rxchannel , AST_OPTION_TONE_VERIFY , & val , sizeof ( char ) , 0 ) ;
ast_channel_setoption ( myrpt - > rxchannel , AST_OPTION_TONE_VERIFY , & val , sizeof ( char ) , 0 ) ;
@ -6228,6 +6311,11 @@ static void *rpt(void *this)
myrpt - > macrotimer - = elap ;
myrpt - > macrotimer - = elap ;
if ( myrpt - > macrotimer < 0 )
if ( myrpt - > macrotimer < 0 )
myrpt - > macrotimer = 0 ;
myrpt - > macrotimer = 0 ;
/* do gosub timers */
if ( myrpt - > gosubtimer )
myrpt - > gosubtimer - = elap ;
if ( myrpt - > gosubtimer < 0 )
myrpt - > gosubtimer = 0 ;
/* Execute scheduler appx. every 2 tenths of a second */
/* Execute scheduler appx. every 2 tenths of a second */
if ( myrpt - > skedtimer < = 0 ) {
if ( myrpt - > skedtimer < = 0 ) {
myrpt - > skedtimer = 200 ;
myrpt - > skedtimer = 200 ;
@ -6248,6 +6336,16 @@ static void *rpt(void *this)
local_dtmf_helper ( myrpt , c ) ;
local_dtmf_helper ( myrpt , c ) ;
} else
} else
rpt_mutex_unlock ( & myrpt - > lock ) ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
c = myrpt - > gosubbuf [ 0 ] ;
if ( c & & ( ! myrpt - > gosubtimer ) ) {
myrpt - > gosubtimer = GOSUBTIME ;
memmove ( myrpt - > gosubbuf , myrpt - > gosubbuf + 1 , sizeof ( myrpt - > gosubbuf ) - 1 ) ;
if ( ( c = = ' p ' ) | | ( c = = ' P ' ) )
myrpt - > gosubtimer = GOSUBPTIME ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
local_dtmf_helper ( myrpt , c ) ;
} else
rpt_mutex_unlock ( & myrpt - > lock ) ;
if ( who = = myrpt - > rxchannel ) { /* if it was a read from rx */
if ( who = = myrpt - > rxchannel ) { /* if it was a read from rx */
f = ast_read ( myrpt - > rxchannel ) ;
f = ast_read ( myrpt - > rxchannel ) ;
if ( ! f ) {
if ( ! f ) {
@ -7072,6 +7170,10 @@ static int rpt_exec(struct ast_channel *chan, void *data)
myrpt - > remchannel = chan ; /* Save copy of channel */
myrpt - > remchannel = chan ; /* Save copy of channel */
snprintf ( myrpt - > macrobuf , sizeof ( myrpt - > macrobuf ) , " PPPP%s " , myrpt - > p . startupmacro ) ;
snprintf ( myrpt - > macrobuf , sizeof ( myrpt - > macrobuf ) , " PPPP%s " , myrpt - > p . startupmacro ) ;
}
}
if ( myrpt - > p . startupgosub ) {
myrpt - > remchannel = chan ; /* Save copy of channel */
snprintf ( myrpt - > gosubbuf , sizeof ( myrpt - > gosubbuf ) , " PPPP%s " , myrpt - > p . startupgosub ) ;
}
myrpt - > reload = 0 ;
myrpt - > reload = 0 ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
setrem ( myrpt ) ;
setrem ( myrpt ) ;
@ -7123,6 +7225,10 @@ static int rpt_exec(struct ast_channel *chan, void *data)
myrpt - > macrotimer - = elap ;
myrpt - > macrotimer - = elap ;
if ( myrpt - > macrotimer < 0 )
if ( myrpt - > macrotimer < 0 )
myrpt - > macrotimer = 0 ;
myrpt - > macrotimer = 0 ;
if ( myrpt - > gosubtimer )
myrpt - > gosubtimer - = elap ;
if ( myrpt - > gosubtimer < 0 )
myrpt - > gosubtimer = 0 ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
if ( ! ms )
if ( ! ms )
continue ;
continue ;
@ -7245,6 +7351,17 @@ static int rpt_exec(struct ast_channel *chan, void *data)
break ;
break ;
continue ;
continue ;
}
}
c = myrpt - > gosubbuf [ 0 ] ;
if ( c & & ( ! myrpt - > gosubtimer ) ) {
myrpt - > gosubtimer = GOSUBTIME ;
memmove ( myrpt - > gosubbuf , myrpt - > gosubbuf + 1 , sizeof ( myrpt - > gosubbuf ) - 1 ) ;
if ( ( c = = ' p ' ) | | ( c = = ' P ' ) )
myrpt - > gosubtimer = GOSUBPTIME ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
if ( handle_remote_dtmf_digit ( myrpt , c , & keyed , 0 ) = = - 1 )
break ;
continue ;
}
rpt_mutex_unlock ( & myrpt - > lock ) ;
rpt_mutex_unlock ( & myrpt - > lock ) ;
continue ;
continue ;
}
}