summaryrefslogtreecommitdiff
path: root/apps/app_rpt.c
diff options
context:
space:
mode:
authorJim Dixon <telesistant@hotmail.com>2006-05-24 07:01:02 +0000
committerJim Dixon <telesistant@hotmail.com>2006-05-24 07:01:02 +0000
commitf2af2718a64c95c19f5ab10f485e9c50828ed365 (patch)
tree375e737ad13b50240d0ff73e7b86d2543e112cff /apps/app_rpt.c
parent99bd06029f70f6a7ec2c0aaa8481edc3e74ea4b0 (diff)
Added incoming audio notch filtering, plus a bunch of command improvements, etc.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@29935 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_rpt.c')
-rw-r--r--apps/app_rpt.c1910
1 files changed, 1468 insertions, 442 deletions
diff --git a/apps/app_rpt.c b/apps/app_rpt.c
index f3edb044d..2ca6fa418 100644
--- a/apps/app_rpt.c
+++ b/apps/app_rpt.c
@@ -1,3 +1,4 @@
+/* #define OLD_ASTERISK */
/*
* Asterisk -- An open source telephony toolkit.
*
@@ -20,7 +21,7 @@
/*! \file
*
* \brief Radio Repeater / Remote Base program
- * version 0.42 02/25/06
+ * version 0.47 05/23/06
*
* \author Jim Dixon, WB6NIL <jim@lambdatel.com>
*
@@ -32,7 +33,18 @@
* Repeater / Remote Functions:
* "Simple" Mode: * - autopatch access, # - autopatch hangup
* Normal mode:
- * See the function list in rpt.conf
+ * See the function list in rpt.conf (autopatchup, autopatchdn)
+ * autopatchup can optionally take comma delimited setting=value pairs:
+ *
+ *
+ * context=string : Override default context with "string"
+ * dialtime=ms : Specify the max number of milliseconds between phone number digits (1000 milliseconds = 1 second)
+ * farenddisconnect=1 : Automatically disconnect when called party hangs up
+ * noct=1 : Don't send repeater courtesy tone during autopatch calls
+ * quiet=1 : Don't send dial tone, or connect messages. Do not send patch down message when called party hangs up
+ *
+ *
+ * Example: 123=autopatchup,dialtime=20000,noct=1,farenddisconnect=1
*
* To send an asterisk (*) while dialing or talking on phone,
* use the autopatch acess code.
@@ -93,6 +105,15 @@
* 140 - Link Status (brief)
*
*
+ *
+ * 'duplex' modes: (defaults to duplex=2)
+ *
+ * 0 - Only remote links key Tx and no main repeat audio.
+ * 1 - Everything other then main Rx keys Tx, no main repeat audio.
+ * 2 - Normal mode
+ * 3 - Normal except no main repeat audio.
+ * 4 - Normal except no main repeat audio during autopatch only
+ *
*/
/*** MODULEINFO
@@ -100,14 +121,15 @@
<defaultenabled>no</defaultenabled>
***/
-/* The following is JUST GROSS!! There is some soft of underlying problem,
- probably in channel_iax2.c, that causes an IAX2 connection to sometimes
- stop transmitting randomly. We have been working for weeks to try to
- locate it and fix it, but to no avail We finally decided to put our
- tail between our legs, and just make the radio system re-connect upon
- network failure. This just shouldnt have to be done. For normal operation,
- comment-out the following line */
-#define RECONNECT_KLUDGE
+/* Un-comment the following to include support for MDC-1200 digital tone
+ signalling protocol (using KA6SQG's GPL'ed implementation) */
+/* file must be downloaded separately, not part of Asterisk distribution */
+/* #include "mdc_decode.c" */
+
+/* Un-comment the following to include support for notch filters in the
+ rx audio stream (using Tony Fisher's mknotch (mkfilter) implementation) */
+/* file must be downloaded separately, not part of Asterisk distribution */
+/* #include "rpt_notch.c" */
/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
@@ -117,6 +139,10 @@
#define MACROPTIME 500
#define DTMF_TIMEOUT 3
+#ifdef __RPT_NOTCH
+#define MAXFILTERS 10
+#endif
+
#define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
#define MAX_RETRIES 5
@@ -124,6 +150,7 @@
#define RETRY_TIMER_MS 5000
+#define MAXPEERSTR 31
#define MAXREMSTR 15
#define DELIMCHR ','
@@ -144,6 +171,8 @@
#define MAXNODESTR 300
+#define MAXPATCHCONTEXT 100
+
#define ACTIONSIZE 32
#define TELEPARAMSIZE 256
@@ -156,7 +185,7 @@ enum {REM_OFF,REM_MONITOR,REM_TX};
enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME,
STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
- TAILMSG, MACRO_NOTFOUND, MACRO_BUSY};
+ TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY};
enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
@@ -215,7 +244,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/say.h"
#include "asterisk/localtime.h"
-static char *tdesc = "Radio Repeater / Remote Base version 0.42 02/25/2006";
+static char *tdesc = "Radio Repeater / Remote Base version 0.47 05/23/2006";
static char *app = "Rpt";
@@ -263,7 +292,9 @@ char *discstr = "!!DISCONNECT!!";
static char *remote_rig_ft897="ft897";
static char *remote_rig_rbi="rbi";
-struct ast_config *cfg;
+#ifdef OLD_ASTERISK
+STANDARD_LOCAL_USER;
+#endif
LOCAL_USER_DECL;
@@ -272,6 +303,7 @@ LOCAL_USER_DECL;
#define TOTIME 180000
#define IDTIME 300000
#define MAXRPTS 20
+#define MAX_STAT_LINKS 32
#define POLITEID 30000
#define FUNCTDELAY 1500
@@ -299,10 +331,24 @@ struct rpt_link
long retrytimer;
long retxtimer;
int retries;
+ int reconnects;
+ long long connecttime;
struct ast_channel *chan;
struct ast_channel *pchan;
} ;
+struct rpt_lstat
+{
+ struct rpt_lstat *next;
+ struct rpt_lstat *prev;
+ char peer[MAXPEERSTR];
+ char name[MAXNODESTR];
+ char mode;
+ char outbound;
+ char reconnects;
+ long long connecttime;
+} ;
+
struct rpt_tele
{
struct rpt_tele *next;
@@ -339,53 +385,77 @@ struct telem_defaults
static struct rpt
{
- char *name;
ast_mutex_t lock;
+ struct ast_config *cfg;
+ char reload;
+
+ char *name;
char *rxchanname;
char *txchanname;
- char *ourcontext;
- char *ourcallerid;
- char *acctcode;
- char *ident;
- char *tonezone;
- char *functions;
- char *link_functions;
- char *phone_functions;
- char *dphone_functions;
- char *nodes;
+ char *remote;
+
+ struct {
+
+ char *ourcontext;
+ char *ourcallerid;
+ char *acctcode;
+ char *ident;
+ char *tonezone;
+ char simple;
+ char *functions;
+ char *link_functions;
+ char *phone_functions;
+ char *dphone_functions;
+ char *nodes;
+ int hangtime;
+ int totime;
+ int idtime;
+ int tailmessagetime;
+ int tailsquashedtime;
+ int duplex;
+ int politeid;
+ char *tailmessages[500];
+ int tailmessagemax;
+ char *memory;
+ char *macro;
+ char *startupmacro;
+ int iobase;
+ char funcchar;
+ char endchar;
+ char nobusyout;
+ } p;
struct rpt_link links;
- int hangtime;
- int totime;
- int idtime;
int unkeytocttimer;
- int duplex;
char keyed;
char exttx;
char localtx;
char remoterx;
char remotetx;
char remoteon;
- char simple;
- char *remote;
char tounkeyed;
char tonotify;
char enable;
char dtmfbuf[MAXDTMF];
char macrobuf[MAXMACRO];
char rem_dtmfbuf[MAXDTMF];
+ char lastdtmfcommand[MAXDTMF];
char cmdnode[50];
struct ast_channel *rxchannel,*txchannel;
struct ast_channel *pchannel,*txpchannel, *remchannel;
struct rpt_tele tele;
+ struct timeval lasttv,curtv;
pthread_t rpt_call_thread,rpt_thread;
time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
- int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer;
+ int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
int mustid,tailid;
- int politeid;
+ int tailevent;
+ int telemrefcount;
int dtmfidx,rem_dtmfidx;
+ int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
+ int totalexecdcommands, dailyexecdcommands;
long retxtimer;
+ long long totaltxtime;
char mydtmf;
- int iobase;
char exten[AST_MAX_EXTENSION];
char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
char offset;
@@ -397,9 +467,12 @@ static struct rpt
char hfscanmode;
int hfscanstatus;
char lastlinknode[MAXNODESTR];
- char funcchar;
- char endchar;
char stopgen;
+ char patchfarenddisconnect;
+ char patchnoct;
+ char patchquiet;
+ char patchcontext[MAXPATCHCONTEXT];
+ int patchdialtime;
int macro_longest;
int phone_longestfunc;
int dphone_longestfunc;
@@ -407,18 +480,31 @@ static struct rpt
int longestfunc;
int longestnode;
int threadrestarts;
- int tailmessagetime;
- int tailsquashedtime;
- char *tailmessages[500];
- int tailmessagemax;
int tailmessagen;
time_t disgorgetime;
time_t lastthreadrestarttime;
long macrotimer;
- char *macro;
- char *startupmacro;
- char *memory;
- char nobusyout;
+ char lastnodewhichkeyedusup[MAXNODESTR];
+#ifdef __RPT_NOTCH
+ struct rptfilter
+ {
+ char desc[100];
+ float x0;
+ float x1;
+ float x2;
+ float y0;
+ float y1;
+ float y2;
+ float gain;
+ float const0;
+ float const1;
+ float const2;
+ } filters[MAXFILTERS];
+#endif
+#ifdef _MDC_DECODE_H_
+ mdc_decoder_t *mdc;
+ unsigned short lastunit;
+#endif
} rpt_vars[MAXRPTS];
@@ -613,6 +699,10 @@ pthread_t id;
/* Debug mode */
static int rpt_do_debug(int fd, int argc, char *argv[]);
static int rpt_do_dump(int fd, int argc, char *argv[]);
+static int rpt_do_stats(int fd, int argc, char *argv[]);
+static int rpt_do_lstats(int fd, int argc, char *argv[]);
+static int rpt_do_reload(int fd, int argc, char *argv[]);
+static int rpt_do_restart(int fd, int argc, char *argv[]);
static char debug_usage[] =
"Usage: rpt debug level {0-7}\n"
@@ -622,6 +712,22 @@ static char dump_usage[] =
"Usage: rpt dump <nodename>\n"
" Dumps struct debug info to log\n";
+static char dump_stats[] =
+"Usage: rpt stats <nodename>\n"
+" Dumps node statistics to console\n";
+
+static char dump_lstats[] =
+"Usage: rpt lstats <nodename>\n"
+" Dumps link statistics to console\n";
+
+static char reload_usage[] =
+"Usage: rpt reload\n"
+" Reloads app_rpt running config parameters\n";
+
+static char restart_usage[] =
+"Usage: rpt restart\n"
+" Restarts app_rpt\n";
+
static struct ast_cli_entry cli_debug =
{ { "rpt", "debug", "level" }, rpt_do_debug,
"Enable app_rpt debugging", debug_usage };
@@ -630,6 +736,22 @@ static struct ast_cli_entry cli_dump =
{ { "rpt", "dump" }, rpt_do_dump,
"Dump app_rpt structs for debugging", dump_usage };
+static struct ast_cli_entry cli_stats =
+ { { "rpt", "stats" }, rpt_do_stats,
+ "Dump node statistics", dump_stats };
+
+static struct ast_cli_entry cli_lstats =
+ { { "rpt", "lstats" }, rpt_do_lstats,
+ "Dump link statistics", dump_lstats };
+
+static struct ast_cli_entry cli_reload =
+ { { "rpt", "reload" }, rpt_do_reload,
+ "Reload app_rpt config", reload_usage };
+
+static struct ast_cli_entry cli_restart =
+ { { "rpt", "restart" }, rpt_do_restart,
+ "Restart app_rpt", restart_usage };
+
/*
* Telemetry defaults
*/
@@ -682,10 +804,20 @@ static struct function_table_tag function_table[] = {
{"remote", function_remote},
{"macro", function_macro}
} ;
+
+/*
+* Break up a delimited string into a table of substrings
+*
+* str - delimited string ( will be modified )
+* strp- list of pointers to substrings (this is built by this function), NULL will be placed at end of list
+* limit- maximum number of substrings to process
+*/
-static int finddelim(char *str,char *strp[])
+
+
+static int finddelim(char *str, char *strp[], int limit)
{
-int i,inquo;
+int i,l,inquo;
inquo = 0;
i = 0;
@@ -695,7 +827,7 @@ int i,inquo;
strp[0] = 0;
return(0);
}
- for(; *str; str++)
+ for(l = 0; *str && (l < limit) ; str++)
{
if (*str == QUOTECHR)
{
@@ -713,6 +845,7 @@ int i,inquo;
if ((*str == DELIMCHR) && (!inquo))
{
*str = 0;
+ l++;
strp[i++] = str + 1;
}
}
@@ -721,6 +854,53 @@ int i,inquo;
}
+/*
+* Match a keyword in a list, and return index of string plus 1 if there was a match,
+* else return 0. If param is passed in non-null, then it will be set to the first character past the match
+*/
+
+static int matchkeyword(char *string, char **param, char *keywords[])
+{
+int i,ls;
+ for( i = 0 ; keywords[i] ; i++){
+ ls = strlen(keywords[i]);
+ if(!ls){
+ *param = NULL;
+ return 0;
+ }
+ if(!strncmp(string, keywords[i], ls)){
+ if(param)
+ *param = string + ls;
+ return i + 1;
+ }
+ }
+ param = NULL;
+ return 0;
+}
+
+/*
+* Skip characters in string which are in charlist, and return a pointer to the
+* first non-matching character
+*/
+
+static char *skipchars(char *string, char *charlist)
+{
+int i;
+ while(*string){
+ for(i = 0; charlist[i] ; i++){
+ if(*string == charlist[i]){
+ string++;
+ break;
+ }
+ }
+ if(!charlist[i])
+ return string;
+ }
+ return string;
+}
+
+
+
static int myatoi(char *str)
{
int ret;
@@ -731,6 +911,248 @@ int ret;
return ret;
}
+
+#ifdef __RPT_NOTCH
+
+/* rpt filter routine */
+static void rpt_filter(struct rpt *myrpt, volatile short *buf, int len)
+{
+int i,j;
+struct rptfilter *f;
+
+ for(i = 0; i < len; i++)
+ {
+ for(j = 0; j < MAXFILTERS; j++)
+ {
+ f = &myrpt->filters[j];
+ if (!*f->desc) continue;
+ f->x0 = f->x1; f->x1 = f->x2;
+ f->x2 = ((float)buf[i]) / f->gain;
+ f->y0 = f->y1; f->y1 = f->y2;
+ f->y2 = (f->x0 + f->x2) + f->const0 * f->x1
+ + (f->const1 * f->y0) + (f->const2 * f->y1);
+ buf[i] = (short)f->y2;
+ }
+ }
+}
+
+#endif
+
+/* Retrieve an int from a config file */
+
+static int retrieve_astcfgint(struct rpt *myrpt,char *category, char *name, int min, int max, int defl)
+{
+ char *var;
+ int ret;
+
+ var = ast_variable_retrieve(myrpt->cfg, category, name);
+ if(var){
+ ret = myatoi(var);
+ if(ret < min)
+ ret = min;
+ if(ret > max)
+ ret = max;
+ }
+ else
+ ret = defl;
+ return ret;
+}
+
+
+static void load_rpt_vars(int n,int init)
+{
+char *this,*val;
+int j,longestnode;
+struct ast_variable *vp;
+struct ast_config *cfg;
+#ifdef __RPT_NOTCH
+int i;
+char *strs[100];
+#endif
+
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "%s config for repeater %s\n",
+ (init) ? "Loading initial" : "Re-Loading",rpt_vars[n].name);
+ ast_mutex_lock(&rpt_vars[n].lock);
+ if (rpt_vars[n].cfg) ast_config_destroy(rpt_vars[n].cfg);
+ cfg = ast_config_load("rpt.conf");
+ if (!cfg) {
+ ast_mutex_unlock(&rpt_vars[n].lock);
+ ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
+ pthread_exit(NULL);
+ }
+ rpt_vars[n].cfg = cfg;
+ this = rpt_vars[n].name;
+ memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
+ if (init)
+ {
+ char *cp;
+ int savearea = (char *)&rpt_vars[n].p - (char *)&rpt_vars[n];
+
+ cp = (char *) &rpt_vars[n].p;
+ memset(cp + sizeof(rpt_vars[n].p),0,
+ sizeof(rpt_vars[n]) - (sizeof(rpt_vars[n].p) + savearea));
+ rpt_vars[n].tele.next = &rpt_vars[n].tele;
+ rpt_vars[n].tele.prev = &rpt_vars[n].tele;
+ rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
+ rpt_vars[n].tailmessagen = 0;
+ }
+#ifdef __RPT_NOTCH
+ /* zot out filters stuff */
+ memset(&rpt_vars[n].filters,0,sizeof(rpt_vars[n].filters));
+#endif
+ val = ast_variable_retrieve(cfg,this,"context");
+ if (val) rpt_vars[n].p.ourcontext = val;
+ else rpt_vars[n].p.ourcontext = this;
+ val = ast_variable_retrieve(cfg,this,"callerid");
+ if (val) rpt_vars[n].p.ourcallerid = val;
+ val = ast_variable_retrieve(cfg,this,"accountcode");
+ if (val) rpt_vars[n].p.acctcode = val;
+ val = ast_variable_retrieve(cfg,this,"idrecording");
+ if (val) rpt_vars[n].p.ident = val;
+ val = ast_variable_retrieve(cfg,this,"hangtime");
+ if (val) rpt_vars[n].p.hangtime = atoi(val);
+ else rpt_vars[n].p.hangtime = HANGTIME;
+ val = ast_variable_retrieve(cfg,this,"totime");
+ if (val) rpt_vars[n].p.totime = atoi(val);
+ else rpt_vars[n].p.totime = TOTIME;
+ rpt_vars[n].p.tailmessagetime = retrieve_astcfgint(&rpt_vars[n],this, "tailmessagetime", 0, 2400000, 0);
+ rpt_vars[n].p.tailsquashedtime = retrieve_astcfgint(&rpt_vars[n],this, "tailsquashedtime", 0, 2400000, 0);
+ rpt_vars[n].p.duplex = retrieve_astcfgint(&rpt_vars[n],this,"duplex",0,4,2);
+ rpt_vars[n].p.idtime = retrieve_astcfgint(&rpt_vars[n],this, "idtime", 60000, 2400000, IDTIME); /* Enforce a min max */
+ rpt_vars[n].p.politeid = retrieve_astcfgint(&rpt_vars[n],this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
+ val = ast_variable_retrieve(cfg,this,"tonezone");
+ if (val) rpt_vars[n].p.tonezone = val;
+ rpt_vars[n].p.tailmessages[0] = 0;
+ rpt_vars[n].p.tailmessagemax = 0;
+ val = ast_variable_retrieve(cfg,this,"tailmessagelist");
+ if (val) rpt_vars[n].p.tailmessagemax = finddelim(val, rpt_vars[n].p.tailmessages, 500);
+ val = ast_variable_retrieve(cfg,this,"memory");
+ if (!val) val = MEMORY;
+ rpt_vars[n].p.memory = val;
+ val = ast_variable_retrieve(cfg,this,"macro");
+ if (!val) val = MACRO;
+ rpt_vars[n].p.macro = val;
+ val = ast_variable_retrieve(cfg,this,"startup_macro");
+ if (val) rpt_vars[n].p.startupmacro = val;
+ val = ast_variable_retrieve(cfg,this,"iobase");
+ /* do not use atoi() here, we need to be able to have
+ the input specified in hex or decimal so we use
+ sscanf with a %i */
+ if ((!val) || (sscanf(val,"%i",&rpt_vars[n].p.iobase) != 1))
+ rpt_vars[n].p.iobase = DEFAULT_IOBASE;
+ val = ast_variable_retrieve(cfg,this,"functions");
+ if (!val)
+ {
+ val = FUNCTIONS;
+ rpt_vars[n].p.simple = 1;
+ }
+ rpt_vars[n].p.functions = val;
+ val = ast_variable_retrieve(cfg,this,"link_functions");
+ if (val) rpt_vars[n].p.link_functions = val;
+ else
+ rpt_vars[n].p.link_functions = rpt_vars[n].p.functions;
+ val = ast_variable_retrieve(cfg,this,"phone_functions");
+ if (val) rpt_vars[n].p.phone_functions = val;
+ val = ast_variable_retrieve(cfg,this,"dphone_functions");
+ if (val) rpt_vars[n].p.dphone_functions = val;
+ val = ast_variable_retrieve(cfg,this,"funcchar");
+ if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
+ rpt_vars[n].p.funcchar = *val;
+ val = ast_variable_retrieve(cfg,this,"endchar");
+ if (!val) rpt_vars[n].p.endchar = ENDCHAR; else
+ rpt_vars[n].p.endchar = *val;
+ val = ast_variable_retrieve(cfg,this,"nobusyout");
+ if (val) rpt_vars[n].p.nobusyout = ast_true(val);
+ val = ast_variable_retrieve(cfg,this,"nodes");
+ if (!val) val = NODES;
+ rpt_vars[n].p.nodes = val;
+#ifdef __RPT_NOTCH
+ val = ast_variable_retrieve(cfg,this,"rxnotch");
+ if (val) {
+ i = finddelim(val,strs,MAXFILTERS * 2);
+ i &= ~1; /* force an even number, rounded down */
+ if (i >= 2) for(j = 0; j < i; j += 2)
+ {
+ rpt_mknotch(atof(strs[j]),atof(strs[j + 1]),
+ &rpt_vars[n].filters[j >> 1].gain,
+ &rpt_vars[n].filters[j >> 1].const0,
+ &rpt_vars[n].filters[j >> 1].const1,
+ &rpt_vars[n].filters[j >> 1].const2);
+ sprintf(rpt_vars[n].filters[j >> 1].desc,"%s Hz, BW = %s",
+ strs[j],strs[j + 1]);
+ }
+
+ }
+#endif
+ longestnode = 0;
+
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.nodes);
+
+ while(vp){
+ j = strlen(vp->name);
+ if (j > longestnode)
+ longestnode = j;
+ vp = vp->next;
+ }
+
+ rpt_vars[n].longestnode = longestnode;
+
+ /*
+ * For this repeater, Determine the length of the longest function
+ */
+ rpt_vars[n].longestfunc = 0;
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].longestfunc)
+ rpt_vars[n].longestfunc = j;
+ vp = vp->next;
+ }
+ /*
+ * For this repeater, Determine the length of the longest function
+ */
+ rpt_vars[n].link_longestfunc = 0;
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.link_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].link_longestfunc)
+ rpt_vars[n].link_longestfunc = j;
+ vp = vp->next;
+ }
+ rpt_vars[n].phone_longestfunc = 0;
+ if (rpt_vars[n].p.phone_functions)
+ {
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.phone_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].phone_longestfunc)
+ rpt_vars[n].phone_longestfunc = j;
+ vp = vp->next;
+ }
+ }
+ rpt_vars[n].dphone_longestfunc = 0;
+ if (rpt_vars[n].p.dphone_functions)
+ {
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.dphone_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].dphone_longestfunc)
+ rpt_vars[n].dphone_longestfunc = j;
+ vp = vp->next;
+ }
+ }
+ rpt_vars[n].macro_longest = 1;
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.macro);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].macro_longest)
+ rpt_vars[n].macro_longest = j;
+ vp = vp->next;
+ }
+ ast_mutex_unlock(&rpt_vars[n].lock);
+}
+
/*
* Enable or disable debug output at a given level at the console
*/
@@ -776,6 +1198,307 @@ static int rpt_do_dump(int fd, int argc, char *argv[])
return RESULT_FAILURE;
}
+/*
+* Dump statistics onto console
+*/
+
+static int rpt_do_stats(int fd, int argc, char *argv[])
+{
+ int i,j;
+ int dailytxtime, dailykerchunks;
+ int totalkerchunks, dailykeyups, totalkeyups, timeouts;
+ int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
+ long long totaltxtime;
+ struct rpt_link *l;
+ char *listoflinks[MAX_STAT_LINKS];
+ char *lastnodewhichkeyedusup, *lastdtmfcommand;
+ char *tot_state, *ider_state, *patch_state;
+ char *reverse_patch_state, *enable_state, *input_signal, *called_number;
+ struct rpt *myrpt;
+
+ static char *not_applicable = "N/A";
+
+ if(argc != 3)
+ return RESULT_SHOWUSAGE;
+
+ for(i = 0 ; i <= MAX_STAT_LINKS; i++)
+ listoflinks[i] = NULL;
+
+ tot_state = ider_state =
+ patch_state = reverse_patch_state =
+ input_signal = called_number =
+ lastdtmfcommand = not_applicable;
+
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcmp(argv[2],rpt_vars[i].name)){
+ /* Make a copy of all stat variables while locked */
+ myrpt = &rpt_vars[i];
+ rpt_mutex_lock(&myrpt->lock); /* LOCK */
+
+ dailytxtime = myrpt->dailytxtime;
+ totaltxtime = myrpt->totaltxtime;
+ dailykeyups = myrpt->dailykeyups;
+ totalkeyups = myrpt->totalkeyups;
+ dailykerchunks = myrpt->dailykerchunks;
+ totalkerchunks = myrpt->totalkerchunks;
+ dailyexecdcommands = myrpt->dailyexecdcommands;
+ totalexecdcommands = myrpt->totalexecdcommands;
+ timeouts = myrpt->timeouts;
+
+ /* Traverse the list of connected nodes */
+ reverse_patch_state = "DOWN";
+ j = 0;
+ l = myrpt->links.next;
+ while(l != &myrpt->links){
+ if (l->name[0] == '0'){ /* Skip '0' nodes */
+ reverse_patch_state = "UP";
+ l = l->next;
+ continue;
+ }
+ listoflinks[j] = ast_strdupa(l->name);
+ if(listoflinks[j])
+ j++;
+ l = l->next;
+ }
+
+ lastnodewhichkeyedusup = ast_strdupa(myrpt->lastnodewhichkeyedusup);
+ if((!lastnodewhichkeyedusup) || (!strlen(lastnodewhichkeyedusup)))
+ lastnodewhichkeyedusup = not_applicable;
+
+ if(myrpt->keyed)
+ input_signal = "YES";
+ else
+ input_signal = "NO";
+
+ if(myrpt->enable)
+ enable_state = "YES";
+ else
+ enable_state = "NO";
+
+ if(!myrpt->totimer)
+ tot_state = "TIMED OUT!";
+ else if(myrpt->totimer != myrpt->p.totime)
+ tot_state = "ARMED";
+ else
+ tot_state = "RESET";
+
+ if(myrpt->tailid)
+ ider_state = "QUEUED IN TAIL";
+ else if(myrpt->mustid)
+ ider_state = "QUEUED FOR CLEANUP";
+ else
+ ider_state = "CLEAN";
+
+ switch(myrpt->callmode){
+ case 1:
+ patch_state = "DIALING";
+ break;
+ case 2:
+ patch_state = "CONNECTING";
+ break;
+ case 3:
+ patch_state = "UP";
+ break;
+
+ case 4:
+ patch_state = "CALL FAILED";
+ break;
+
+ default:
+ patch_state = "DOWN";
+ }
+
+ if(strlen(myrpt->exten)){
+ called_number = ast_strdupa(myrpt->exten);
+ if(!called_number)
+ called_number = not_applicable;
+ }
+
+ if(strlen(myrpt->lastdtmfcommand)){
+ lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
+ if(!lastdtmfcommand)
+ lastdtmfcommand = not_applicable;
+ }
+
+ rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
+
+ ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
+ ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
+ ast_cli(fd, "Transmitter enabled..............................: %s\n", enable_state);
+ ast_cli(fd, "Time out timer state.............................: %s\n", tot_state);
+ ast_cli(fd, "Time outs since system initialization............: %d\n", timeouts);
+ ast_cli(fd, "Identifier state.................................: %s\n", ider_state);
+ ast_cli(fd, "Kerchunks today..................................: %d\n", dailykerchunks);
+ ast_cli(fd, "Kerchunks since system initialization............: %d\n", totalkerchunks);
+ ast_cli(fd, "Keyups today.....................................: %d\n", dailykeyups);
+ ast_cli(fd, "Keyups since system initialization...............: %d\n", totalkeyups);
+ ast_cli(fd, "DTMF commands today..............................: %d\n", dailyexecdcommands);
+ ast_cli(fd, "DTMF commands since system initialization........: %d\n", totalexecdcommands);
+ ast_cli(fd, "Last DTMF command executed.......................: %s\n", lastdtmfcommand);
+
+ hours = dailytxtime/3600000;
+ dailytxtime %= 3600000;
+ minutes = dailytxtime/60000;
+ dailytxtime %= 60000;
+ seconds = dailytxtime/1000;
+ dailytxtime %= 1000;
+
+ ast_cli(fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
+ hours, minutes, seconds, dailytxtime);
+
+ hours = (int) totaltxtime/3600000;
+ totaltxtime %= 3600000;
+ minutes = (int) totaltxtime/60000;
+ totaltxtime %= 60000;
+ seconds = (int) totaltxtime/1000;
+ totaltxtime %= 1000;
+
+ ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
+ hours, minutes, seconds, (int) totaltxtime);
+ ast_cli(fd, "Nodes currently connected to us..................: ");
+ for(j = 0 ;; j++){
+ if(!listoflinks[j]){
+ if(!j){
+ ast_cli(fd,"<NONE>");
+ }
+ break;
+ }
+ ast_cli(fd, "%s", listoflinks[j]);
+ if(j % 4 == 3){
+ ast_cli(fd, "\n");
+ ast_cli(fd, " : ");
+ }
+ else{
+ if(listoflinks[j + 1])
+ ast_cli(fd, ", ");
+ }
+ }
+ ast_cli(fd,"\n");
+
+ ast_cli(fd, "Last node which transmitted to us................: %s\n", lastnodewhichkeyedusup);
+ ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
+ ast_cli(fd, "Autopatch called number..........................: %s\n", called_number);
+ ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n\n", reverse_patch_state);
+
+ return RESULT_SUCCESS;
+ }
+ }
+ return RESULT_FAILURE;
+}
+
+/*
+* Link stats function
+*/
+
+static int rpt_do_lstats(int fd, int argc, char *argv[])
+{
+ int i,j;
+ struct rpt *myrpt;
+ struct rpt_link *l;
+ struct rpt_lstat *s,*t;
+ struct rpt_lstat s_head;
+ if(argc != 3)
+ return RESULT_SHOWUSAGE;
+
+ s = NULL;
+ s_head.next = &s_head;
+ s_head.prev = &s_head;
+
+ for(i = 0; i < nrpts; i++)
+ {
+ if (!strcmp(argv[2],rpt_vars[i].name)){
+ /* Make a copy of all stat variables while locked */
+ myrpt = &rpt_vars[i];
+ rpt_mutex_lock(&myrpt->lock); /* LOCK */
+ /* Traverse the list of connected nodes */
+ j = 0;
+ l = myrpt->links.next;
+ while(l != &myrpt->links){
+ if (l->name[0] == '0'){ /* Skip '0' nodes */
+ l = l->next;
+ continue;
+ }
+ if((s = (struct rpt_lstat *) malloc(sizeof(struct rpt_lstat))) == NULL){
+ ast_log(LOG_ERROR, "Malloc failed in rpt_do_lstats\n");
+ rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
+ return RESULT_FAILURE;
+ }
+ memset(s, 0, sizeof(struct rpt_lstat));
+ strncpy(s->name, l->name, MAXREMSTR - 1);
+ pbx_substitute_variables_helper(l->chan, "${IAXPEER(CURRENTCHANNEL)}", s->peer, MAXPEERSTR - 1);
+ s->mode = l->mode;
+ s->outbound = l->outbound;
+ s->reconnects = l->reconnects;
+ s->connecttime = l->connecttime;
+ insque((struct qelem *) s, (struct qelem *) s_head.next);
+ l = l->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
+ ast_cli(fd, "NODE PEER RECONNECTS DIRECTION CONNECT TIME\n");
+ ast_cli(fd, "---- ---- ---------- --------- ------------\n");
+
+ for(s = s_head.next; s != &s_head; s = s->next){
+ int hours, minutes, seconds;
+ long long connecttime = s->connecttime;
+ char conntime[31];
+ hours = (int) connecttime/3600000;
+ connecttime %= 3600000;
+ minutes = (int) connecttime/60000;
+ connecttime %= 60000;
+ seconds = (int) connecttime/1000;
+ connecttime %= 1000;
+ snprintf(conntime, 30, "%02d:%02d:%02d.%d",
+ hours, minutes, seconds, (int) connecttime);
+ conntime[30] = 0;
+ ast_cli(fd, "%-10s%-20s%-12d%-11s%-30s\n",
+ s->name, s->peer, s->reconnects, (s->outbound)? "OUT":"IN", conntime);
+ }
+ /* destroy our local link queue */
+ s = s_head.next;
+ while(s != &s_head){
+ t = s;
+ s = s->next;
+ remque((struct qelem *)t);
+ free(t);
+ }
+ return RESULT_SUCCESS;
+ }
+ }
+ return RESULT_FAILURE;
+}
+
+/*
+* reload vars
+*/
+
+static int rpt_do_reload(int fd, int argc, char *argv[])
+{
+int n;
+
+ if (argc > 2) return RESULT_SHOWUSAGE;
+
+ for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
+
+ return RESULT_FAILURE;
+}
+
+/*
+* restart app_rpt
+*/
+
+static int rpt_do_restart(int fd, int argc, char *argv[])
+{
+int i;
+
+ if (argc > 2) return RESULT_SHOWUSAGE;
+ for(i = 0; i < nrpts; i++)
+ {
+ if (rpt_vars[i].rxchannel) ast_softhangup(rpt_vars[i].rxchannel,AST_SOFTHANGUP_DEV);
+ }
+ return RESULT_FAILURE;
+}
+
static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
{
int res;
@@ -1054,27 +1777,7 @@ static int saynum(struct ast_channel *mychannel, int num)
}
-/* Retrieve an int from a config file */
-
-static int retrieve_astcfgint(char *category, char *name, int min, int max, int defl)
-{
- char *var;
- int ret;
-
- var = ast_variable_retrieve(cfg, category, name);
- if(var){
- ret = myatoi(var);
- if(ret < min)
- ret = min;
- if(ret > max)
- ret = max;
- }
- else
- ret = defl;
- return ret;
-}
-
-static int telem_any(struct ast_channel *chan, char *entry)
+static int telem_any(struct rpt *myrpt,struct ast_channel *chan, char *entry)
{
int res;
char c;
@@ -1089,11 +1792,11 @@ static int telem_any(struct ast_channel *chan, char *entry)
res = 0;
if(!morseidfreq){ /* Get the morse parameters if not already loaded */
- morsespeed = retrieve_astcfgint( mcat, "speed", 5, 20, 20);
- morsefreq = retrieve_astcfgint( mcat, "frequency", 300, 3000, 800);
- morseampl = retrieve_astcfgint( mcat, "amplitude", 200, 8192, 4096);
- morseidampl = retrieve_astcfgint( mcat, "idamplitude", 200, 8192, 2048);
- morseidfreq = retrieve_astcfgint( mcat, "idfrequency", 300, 3000, 330);
+ morsespeed = retrieve_astcfgint(myrpt, mcat, "speed", 5, 20, 20);
+ morsefreq = retrieve_astcfgint(myrpt, mcat, "frequency", 300, 3000, 800);
+ morseampl = retrieve_astcfgint(myrpt, mcat, "amplitude", 200, 8192, 4096);
+ morseidampl = retrieve_astcfgint(myrpt, mcat, "idamplitude", 200, 8192, 2048);
+ morseidfreq = retrieve_astcfgint(myrpt, mcat, "idfrequency", 300, 3000, 330);
}
/* Is it a file, or a tone sequence? */
@@ -1130,7 +1833,7 @@ static int telem_any(struct ast_channel *chan, char *entry)
* 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
*/
-static int telem_lookup(struct ast_channel *chan, char *node, char *name)
+static int telem_lookup(struct rpt *myrpt,struct ast_channel *chan, char *node, char *name)
{
int res;
@@ -1143,21 +1846,19 @@ static int telem_lookup(struct ast_channel *chan, char *node, char *name)
telemetry_save = NULL;
entry = NULL;
-
/* Retrieve the section name for telemetry from the node section */
-
- telemetry = ast_variable_retrieve(cfg, node, TELEMETRY);
- if(telemetry){
+ telemetry = ast_variable_retrieve(myrpt->cfg, node, TELEMETRY);
+ if(telemetry ){
telemetry_save = ast_strdupa(telemetry);
if(!telemetry_save){
ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
return res;
}
- entry = ast_variable_retrieve(cfg, telemetry_save, name);
+ entry = ast_variable_retrieve(myrpt->cfg, telemetry_save, name);
}
- /* Try to look up the telemetry name */
-
+ /* Try to look up the telemetry name */
+
if(!entry){
/* Telemetry name wasn't found in the config file, use the default */
for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
@@ -1165,10 +1866,11 @@ static int telem_lookup(struct ast_channel *chan, char *node, char *name)
entry = tele_defs[i].value;
}
}
- if(entry)
- telem_any(chan, entry);
+ if(entry){
+ if(strlen(entry))
+ telem_any(myrpt,chan, entry);
+ }
else{
- ast_log(LOG_WARNING, "Telemetry name not found: %s\n", name);
res = -1;
}
return res;
@@ -1185,7 +1887,7 @@ static int get_wait_interval(struct rpt *myrpt, int type)
char *wait_times_save;
wait_times_save = NULL;
- wait_times = ast_variable_retrieve(cfg, myrpt->name, "wait_times");
+ wait_times = ast_variable_retrieve(myrpt->cfg, myrpt->name, "wait_times");
if(wait_times){
wait_times_save = ast_strdupa(wait_times);
@@ -1198,28 +1900,28 @@ static int get_wait_interval(struct rpt *myrpt, int type)
switch(type){
case DLY_TELEM:
if(wait_times)
- interval = retrieve_astcfgint(wait_times_save, "telemwait", 500, 5000, 1000);
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "telemwait", 500, 5000, 1000);
else
interval = 1000;
break;
case DLY_ID:
if(wait_times)
- interval = retrieve_astcfgint(wait_times_save, "idwait",250,5000,500);
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "idwait",250,5000,500);
else
interval = 500;
break;
case DLY_UNKEY:
if(wait_times)
- interval = retrieve_astcfgint(wait_times_save, "unkeywait",500,5000,1000);
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "unkeywait",500,5000,1000);
else
interval = 1000;
break;
case DLY_CALLTERM:
if(wait_times)
- interval = retrieve_astcfgint(wait_times_save, "calltermwait",500,5000,1500);
+ interval = retrieve_astcfgint(myrpt,wait_times_save, "calltermwait",500,5000,1500);
else
interval = 1500;
break;
@@ -1239,8 +1941,13 @@ static int get_wait_interval(struct rpt *myrpt, int type)
static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
{
int interval;
- if((interval = get_wait_interval(myrpt, type)))
+ interval = get_wait_interval(myrpt, type);
+ if(debug)
+ ast_log(LOG_NOTICE," Delay interval = %d\n", interval);
+ if(interval)
ast_safe_sleep(chan,interval);
+ if(debug)
+ ast_log(LOG_NOTICE,"Delay complete\n");
return;
}
@@ -1264,9 +1971,8 @@ struct tm localtm;
/* Snag copies of a few key myrpt variables */
rpt_mutex_lock(&myrpt->lock);
- insque((struct qelem *)mytele, (struct qelem *)myrpt->tele.next); /* Moved from rpt_telemetry() */
nodename = ast_strdupa(myrpt->name);
- ident = ast_strdupa(myrpt->ident);
+ ident = ast_strdupa(myrpt->p.ident);
rpt_mutex_unlock(&myrpt->lock);
/* allocate a pseudo-channel thru asterisk */
@@ -1314,35 +2020,41 @@ struct tm localtm;
case ID1:
/* wait a bit */
wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
- res = telem_any(mychannel, ident);
+ res = telem_any(myrpt,mychannel, ident);
imdone=1;
break;
case TAILMSG:
- res = ast_streamfile(mychannel, myrpt->tailmessages[myrpt->tailmessagen], mychannel->language);
+ res = ast_streamfile(mychannel, myrpt->p.tailmessages[myrpt->tailmessagen], mychannel->language);
break;
case IDTALKOVER:
- p = ast_variable_retrieve(cfg, nodename, "idtalkover");
+ p = ast_variable_retrieve(myrpt->cfg, nodename, "idtalkover");
if(p)
- res = telem_any(mychannel, p);
+ res = telem_any(myrpt,mychannel, p);
imdone=1;
break;
case PROC:
/* wait a little bit longer */
wait_interval(myrpt, DLY_TELEM, mychannel);
- res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
+ res = telem_lookup(myrpt, mychannel, myrpt->name, "patchup");
+ if(res < 0){ /* Then default message */
+ res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
+ }
break;
case TERM:
/* wait a little bit longer */
wait_interval(myrpt, DLY_CALLTERM, mychannel);
- res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
+ res = telem_lookup(myrpt, mychannel, myrpt->name, "patchdown");
+ if(res < 0){ /* Then default message */
+ res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
+ }
break;
case COMPLETE:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
- res = telem_lookup(mychannel, myrpt->name, "functcomplete");
+ res = telem_lookup(myrpt,mychannel, myrpt->name, "functcomplete");
break;
case MACRO_NOTFOUND:
/* wait a little bit */
@@ -1355,7 +2067,11 @@ struct tm localtm;
res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
break;
case UNKEY:
-
+ if(myrpt->patchnoct && myrpt->callmode){ /* If no CT during patch configured, then don't send one */
+ imdone = 1;
+ break;
+ }
+
/*
* Reset the Unkey to CT timer
*/
@@ -1411,7 +2127,12 @@ struct tm localtm;
imdone = 1;
break;
}
-
+
+ rpt_mutex_lock(&myrpt->lock); /* Update the kerchunk counters */
+ myrpt->dailykerchunks++;
+ myrpt->totalkerchunks++;
+ rpt_mutex_unlock(&myrpt->lock);
+
haslink = 0;
hastx = 0;
hasremote = 0;
@@ -1438,7 +2159,7 @@ struct tm localtm;
if (haslink)
{
- res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
+ res = telem_lookup(myrpt,mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
if(res)
ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
@@ -1447,15 +2168,15 @@ struct tm localtm;
if (myrpt->cmdnode[0])
{
ast_safe_sleep(mychannel,200);
- res = telem_lookup(mychannel, myrpt->name, "cmdmode");
+ res = telem_lookup(myrpt,mychannel, myrpt->name, "cmdmode");
if(res)
ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
}
}
- else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
+ else if((ct = ast_variable_retrieve(myrpt->cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
ct_copy = ast_strdupa(ct);
- res = telem_lookup(mychannel, myrpt->name, ct_copy);
+ res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
@@ -1477,14 +2198,42 @@ struct tm localtm;
ast_hangup(mychannel);
pthread_exit(NULL);
}
- if((ct = ast_variable_retrieve(cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
+ if((ct = ast_variable_retrieve(myrpt->cfg, nodename, "remotect"))){ /* Unlinked Courtesy Tone */
ast_safe_sleep(mychannel,200);
ct_copy = ast_strdupa(ct);
- res = telem_lookup(mychannel, myrpt->name, ct_copy);
+ res = telem_lookup(myrpt,mychannel, myrpt->name, ct_copy);
if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
}
+#ifdef _MDC_DECODE_H_
+ if (myrpt->lastunit)
+ {
+ char mystr[10];
+
+ ast_safe_sleep(mychannel,200);
+ /* set for all to hear */
+ ci.chan = 0;
+ ci.confno = myrpt->txconf;
+ ci.confmode = ZT_CONF_CONFANN;
+ /* first put the channel on the conference in announce mode */
+ if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ rpt_mutex_lock(&myrpt->lock);
+ remque((struct qelem *)mytele);
+ rpt_mutex_unlock(&myrpt->lock);
+ ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+ free(mytele);
+ ast_hangup(mychannel);
+ pthread_exit(NULL);
+ }
+ sprintf(mystr,"%04x",myrpt->lastunit);
+ myrpt->lastunit = 0;
+ ast_say_character_str(mychannel,mystr,NULL,mychannel->language);
+ break;
+ }
+#endif
imdone = 1;
break;
case REMDISC:
@@ -1637,6 +2386,34 @@ struct tm localtm;
}
imdone = 1;
break;
+
+ case LASTNODEKEY: /* Identify last node which keyed us up */
+ rpt_mutex_lock(&myrpt->lock);
+ if(myrpt->lastnodewhichkeyedusup)
+ p = ast_strdupa(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
+ else
+ p = NULL;
+ rpt_mutex_unlock(&myrpt->lock);
+ if(!p){
+ imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */
+ break;
+ }
+ wait_interval(myrpt, DLY_TELEM, mychannel);
+ res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
+ if (!res)
+ res = ast_waitstream(mychannel, "");
+ else
+ ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+ ast_stopstream(mychannel);
+ ast_say_character_str(mychannel, p, NULL, mychannel->language);
+ if (!res)
+ res = ast_waitstream(mychannel, "");
+ else
+ ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+ ast_stopstream(mychannel);
+ imdone = 1;
+ break;
+
case TIMEOUT:
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
@@ -1784,11 +2561,11 @@ struct tm localtm;
if (!res)
{
myrpt->tailmessagen++;
- if(myrpt->tailmessagen >= myrpt->tailmessagemax) myrpt->tailmessagen = 0;
+ if(myrpt->tailmessagen >= myrpt->p.tailmessagemax) myrpt->tailmessagen = 0;
}
else
{
- myrpt->tmsgtimer = myrpt->tailsquashedtime;
+ myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
}
}
remque((struct qelem *)mytele);
@@ -1838,12 +2615,17 @@ pthread_attr_t attr;
strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
tele->param[TELEPARAMSIZE - 1] = 0;
}
+ insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
rpt_mutex_unlock(&myrpt->lock);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
- if(res < 0)
+ if(res < 0){
+ rpt_mutex_lock(&myrpt->lock);
+ remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */
+ rpt_mutex_unlock(&myrpt->lock);
ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
+ }
return;
}
@@ -1853,9 +2635,10 @@ ZT_CONFINFO ci; /* conference info */
struct rpt *myrpt = (struct rpt *)this;
int res;
struct ast_frame wf;
-int stopped,congstarted;
+int stopped,congstarted,dialtimer,lastcidx,aborted;
struct ast_channel *mychannel,*genchannel;
+
myrpt->mydtmf = 0;
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
@@ -1897,24 +2680,24 @@ struct ast_channel *mychannel,*genchannel;
myrpt->callmode = 0;
pthread_exit(NULL);
}
- if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
+ if (myrpt->p.tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->p.tonezone) == -1))
{
- ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
+ ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
- if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
+ if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->p.tonezone) == -1))
{
- ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
+ ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->p.tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
- /* start dialtone */
- if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
+ /* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
+ if ((!myrpt->patchquiet) && (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0))
{
ast_log(LOG_WARNING, "Cannot start dialtone\n");
ast_hangup(mychannel);
@@ -1924,20 +2707,40 @@ struct ast_channel *mychannel,*genchannel;
}
stopped = 0;
congstarted = 0;
+ dialtimer = 0;
+ lastcidx = 0;
+ aborted = 0;
+
+
while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
{
- if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
+ if((myrpt->patchdialtime)&&(myrpt->callmode == 1)&&(myrpt->cidx != lastcidx)){
+ dialtimer = 0;
+ lastcidx = myrpt->cidx;
+ }
+
+ if((myrpt->patchdialtime)&&(dialtimer >= myrpt->patchdialtime)){
+ rpt_mutex_lock(&myrpt->lock);
+ aborted = 1;
+ myrpt->callmode = 0;
+ rpt_mutex_unlock(&myrpt->lock);
+ break;
+ }
+
+ if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0))
{
stopped = 1;
/* stop dial tone */
tone_zone_play_tone(mychannel->fds[0],-1);
}
- if ((myrpt->callmode == 4) && (!congstarted))
+ if (myrpt->callmode == 4)
{
- congstarted = 1;
- /* start congestion tone */
- tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
+ if(!congstarted){
+ congstarted = 1;
+ /* start congestion tone */
+ tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
+ }
}
res = ast_safe_sleep(mychannel, MSWAIT);
if (res < 0)
@@ -1949,6 +2752,7 @@ struct ast_channel *mychannel,*genchannel;
rpt_mutex_unlock(&myrpt->lock);
pthread_exit(NULL);
}
+ dialtimer += MSWAIT;
}
/* stop any tone generation */
tone_zone_play_tone(mychannel->fds[0],-1);
@@ -1960,12 +2764,14 @@ struct ast_channel *mychannel,*genchannel;
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 0;
rpt_mutex_unlock(&myrpt->lock);
+ if((!myrpt->patchquiet) && aborted)
+ rpt_telemetry(myrpt, TERM, NULL);
pthread_exit(NULL);
}
- if (myrpt->ourcallerid && *myrpt->ourcallerid){
+ if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid){
char *name, *loc, *instr;
- instr = strdup(myrpt->ourcallerid);
+ instr = strdup(myrpt->p.ourcallerid);
if(instr){
ast_callerid_parse(instr, &name, &loc);
if(loc){
@@ -1983,9 +2789,10 @@ struct ast_channel *mychannel,*genchannel;
}
strncpy(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
- strncpy(mychannel->context, myrpt->ourcontext, sizeof(mychannel->context) - 1);
- if (myrpt->acctcode)
- ast_string_field_set(mychannel, accountcode, myrpt->acctcode);
+ strncpy(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context) - 1);
+
+ if (myrpt->p.acctcode)
+ strncpy((char *)mychannel->accountcode, myrpt->p.acctcode, sizeof(mychannel->accountcode) - 1);
mychannel->priority = 1;
ast_channel_undefer_dtmf(mychannel);
if (ast_pbx_start(mychannel) < 0)
@@ -2001,15 +2808,39 @@ struct ast_channel *mychannel,*genchannel;
usleep(10000);
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 3;
+ /* set appropriate conference for the pseudo */
+ ci.chan = 0;
+ ci.confno = myrpt->conf;
+ ci.confmode = (myrpt->p.duplex == 2) ? ZT_CONF_CONFANNMON :
+ (ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
+ /* first put the channel on the conference in announce mode */
+ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ ast_hangup(mychannel);
+ ast_hangup(genchannel);
+ myrpt->callmode = 0;
+ pthread_exit(NULL);
+ }
while(myrpt->callmode)
{
if ((!mychannel->pbx) && (myrpt->callmode != 4))
{
- myrpt->callmode = 4;
- rpt_mutex_unlock(&myrpt->lock);
- /* start congestion tone */
- tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
- rpt_mutex_lock(&myrpt->lock);
+ if(myrpt->patchfarenddisconnect){ /* If patch is setup for far end disconnect */
+ myrpt->callmode = 0;
+ if(!myrpt->patchquiet){
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt, TERM, NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ }
+ else{ /* Send congestion until patch is downed by command */
+ myrpt->callmode = 4;
+ rpt_mutex_unlock(&myrpt->lock);
+ /* start congestion tone */
+ tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
+ rpt_mutex_lock(&myrpt->lock);
+ }
}
if (myrpt->mydtmf)
{
@@ -2036,6 +2867,16 @@ struct ast_channel *mychannel,*genchannel;
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 0;
rpt_mutex_unlock(&myrpt->lock);
+ /* set appropriate conference for the pseudo */
+ ci.chan = 0;
+ ci.confno = myrpt->conf;
+ ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
+ (ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
+ /* first put the channel on the conference in announce mode */
+ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
+ {
+ ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+ }
pthread_exit(NULL);
}
@@ -2092,6 +2933,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
char tmp[300], deststr[300] = "",modechange = 0;
char digitbuf[MAXNODESTR];
struct rpt_link *l;
+ int reconnects = 0;
ZT_CONFINFO ci; /* conference info */
if(!param)
@@ -2110,7 +2952,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
case 1: /* Link off */
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
strcpy(digitbuf,myrpt->lastlinknode);
- val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
@@ -2136,7 +2978,6 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
}
if (l != &myrpt->links){ /* if found */
struct ast_frame wf;
-
strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
l->retries = MAX_RETRIES + 1;
l->disced = 1;
@@ -2162,7 +3003,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
case 2: /* Link Monitor */
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
strcpy(digitbuf,myrpt->lastlinknode);
- val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
@@ -2196,6 +3037,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
return DC_COMPLETE;
}
+ reconnects = l->reconnects;
rpt_mutex_unlock(&myrpt->lock);
if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
l->retries = MAX_RETRIES + 1;
@@ -2270,6 +3112,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
return DC_ERROR;
}
rpt_mutex_lock(&myrpt->lock);
+ l->reconnects = reconnects;
/* insert at end of queue */
insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
rpt_mutex_unlock(&myrpt->lock);
@@ -2278,7 +3121,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
case 3: /* Link transceive */
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
strcpy(digitbuf,myrpt->lastlinknode);
- val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
@@ -2310,6 +3153,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
rpt_telemetry(myrpt, REMALREADY, NULL);
return DC_COMPLETE;
}
+ reconnects = l->reconnects;
rpt_mutex_unlock(&myrpt->lock);
if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
l->retries = MAX_RETRIES + 1;
@@ -2386,6 +3230,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
return DC_ERROR;
}
rpt_mutex_lock(&myrpt->lock);
+ l->reconnects = reconnects;
/* insert at end of queue */
insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
rpt_mutex_unlock(&myrpt->lock);
@@ -2406,7 +3251,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
strcpy(digitbuf,myrpt->lastlinknode);
/* node must at least exist in list */
- val = ast_variable_retrieve(cfg, myrpt->nodes, digitbuf);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
@@ -2428,12 +3273,16 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
case 6: /* All Links Off */
l = myrpt->links.next;
- while(l != &myrpt->links){
+ while(l != &myrpt->links){ /* This code is broke and needs to be changed to work with the reconnect kludge */
if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
l = l->next;
}
rpt_telemetry(myrpt, COMPLETE, NULL);
break;
+
+ case 7: /* Identify last node which keyed us up */
+ rpt_telemetry(myrpt, LASTNODEKEY, NULL);
+ break;
default:
return DC_ERROR;
@@ -2450,7 +3299,19 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digits, int comm
static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
{
pthread_attr_t attr;
-
+ int i, index, paramlength;
+ char *lparam;
+ char *value = NULL;
+ char *paramlist[20];
+
+ static char *keywords[] = {
+ "context",
+ "dialtime",
+ "farenddisconnect",
+ "noct",
+ "quiet",
+ NULL
+ };
if (!myrpt->enable)
return DC_ERROR;
@@ -2458,12 +3319,61 @@ static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf,
if(debug)
printf("@@@@ Autopatch up\n");
+ if(!myrpt->callmode){
+ /* Set defaults */
+ myrpt->patchnoct = 0;
+ myrpt->patchdialtime = 0;
+ myrpt->patchfarenddisconnect = 0;
+ myrpt->patchquiet = 0;
+ strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
+
+ if(param){
+ /* Process parameter list */
+ lparam = ast_strdupa(param);
+ if(!lparam){
+ ast_log(LOG_ERROR,"App_rpt out of memory on line %d\n",__LINE__);
+ return DC_ERROR;
+ }
+ paramlength = finddelim(lparam, paramlist, 20);
+ for(i = 0; i < paramlength; i++){
+ index = matchkeyword(paramlist[i], &value, keywords);
+ if(value)
+ value = skipchars(value, "= ");
+ switch(index){
+
+ case 1: /* context */
+ strncpy(myrpt->patchcontext, value, MAXPATCHCONTEXT - 1) ;
+ break;
+
+ case 2: /* dialtime */
+ myrpt->patchdialtime = atoi(value);
+ break;
+
+ case 3: /* farenddisconnect */
+ myrpt->patchfarenddisconnect = atoi(value);
+ break;
+
+ case 4: /* noct */
+ myrpt->patchnoct = atoi(value);
+ break;
+
+ case 5: /* quiet */
+ myrpt->patchquiet = atoi(value);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
rpt_mutex_lock(&myrpt->lock);
-
+
/* if on call, force * into current audio stream */
if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
- myrpt->mydtmf = myrpt->funcchar;
+ myrpt->mydtmf = myrpt->p.funcchar;
}
if (myrpt->callmode){
rpt_mutex_unlock(&myrpt->lock);
@@ -2562,8 +3472,8 @@ struct ast_channel *mychannel;
return DC_ERROR;
}
- if (*digitbuf == '0') val = myrpt->startupmacro;
- else val = ast_variable_retrieve(cfg, myrpt->macro, digitbuf);
+ if (*digitbuf == '0') val = myrpt->p.startupmacro;
+ else val = ast_variable_retrieve(myrpt->cfg, myrpt->p.macro, digitbuf);
/* param was 1 for local buf */
if (!val){
rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
@@ -2631,7 +3541,7 @@ static int collect_function_digits(struct rpt *myrpt, char *digits,
int i;
char *stringp,*action,*param,*functiondigits;
char function_table_name[30] = "";
- char workstring[80];
+ char workstring[200];
struct ast_variable *vp;
@@ -2639,18 +3549,18 @@ static int collect_function_digits(struct rpt *myrpt, char *digits,
printf("@@@@ Digits collected: %s, source: %d\n", digits, command_source);
if (command_source == SOURCE_DPHONE) {
- if (!myrpt->dphone_functions) return DC_INDETERMINATE;
- strncpy(function_table_name, myrpt->dphone_functions, sizeof(function_table_name) - 1);
+ if (!myrpt->p.dphone_functions) return DC_INDETERMINATE;
+ strncpy(function_table_name, myrpt->p.dphone_functions, sizeof(function_table_name) - 1);
}
else if (command_source == SOURCE_PHONE) {
- if (!myrpt->phone_functions) return DC_INDETERMINATE;
- strncpy(function_table_name, myrpt->phone_functions, sizeof(function_table_name) - 1);
+ if (!myrpt->p.phone_functions) return DC_INDETERMINATE;
+ strncpy(function_table_name, myrpt->p.phone_functions, sizeof(function_table_name) - 1);
}
else if (command_source == SOURCE_LNK)
- strncpy(function_table_name, myrpt->link_functions, sizeof(function_table_name) - 1);
+ strncpy(function_table_name, myrpt->p.link_functions, sizeof(function_table_name) - 1);
else
- strncpy(function_table_name, myrpt->functions, sizeof(function_table_name) - 1);
- vp = ast_variable_browse(cfg, function_table_name);
+ strncpy(function_table_name, myrpt->p.functions, sizeof(function_table_name) - 1);
+ vp = ast_variable_browse(myrpt->cfg, function_table_name);
while(vp) {
if(!strncasecmp(vp->name, digits, strlen(vp->name)))
break;
@@ -2795,21 +3705,23 @@ struct ast_frame wf;
return;
}
rpt_mutex_lock(&myrpt->lock);
- if (c == myrpt->endchar) myrpt->stopgen = 1;
+ if (c == myrpt->p.endchar) myrpt->stopgen = 1;
if (myrpt->callmode == 1)
{
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
- if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
{
myrpt->callmode = 2;
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt,PROC,NULL);
- rpt_mutex_lock(&myrpt->lock);
+ if(!myrpt->patchquiet){
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt,PROC,NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
}
/* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
{
/* call has failed, inform user */
myrpt->callmode = 4;
@@ -2819,7 +3731,7 @@ struct ast_frame wf;
{
myrpt->mydtmf = c;
}
- if (c == myrpt->funcchar)
+ if (c == myrpt->p.funcchar)
{
myrpt->rem_dtmfidx = 0;
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
@@ -2827,7 +3739,7 @@ struct ast_frame wf;
rpt_mutex_unlock(&myrpt->lock);
return;
}
- else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
+ else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
{
time(&myrpt->rem_dtmf_time);
if (myrpt->rem_dtmfidx < MAXDTMF)
@@ -2852,6 +3764,10 @@ struct ast_frame wf;
case DC_COMPLETE:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
myrpt->rem_dtmfbuf[0] = 0;
myrpt->rem_dtmfidx = -1;
myrpt->rem_dtmf_time = 0;
@@ -2879,7 +3795,7 @@ char cmd[300];
int res;
rpt_mutex_lock(&myrpt->lock);
- if (c == myrpt->endchar)
+ if (c == myrpt->p.endchar)
{
if (mylink->lastrx)
{
@@ -2909,15 +3825,17 @@ int res;
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
- if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
{
myrpt->callmode = 2;
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt,PROC,NULL);
- rpt_mutex_lock(&myrpt->lock);
+ if(!myrpt->patchquiet){
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt,PROC,NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
}
/* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
{
/* call has failed, inform user */
myrpt->callmode = 4;
@@ -2927,7 +3845,7 @@ int res;
{
myrpt->mydtmf = c;
}
- if (c == myrpt->funcchar)
+ if (c == myrpt->p.funcchar)
{
myrpt->rem_dtmfidx = 0;
myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
@@ -2935,7 +3853,7 @@ int res;
rpt_mutex_unlock(&myrpt->lock);
return;
}
- else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
+ else if ((c != myrpt->p.endchar) && (myrpt->rem_dtmfidx >= 0))
{
time(&myrpt->rem_dtmf_time);
if (myrpt->rem_dtmfidx < MAXDTMF)
@@ -2979,6 +3897,10 @@ int res;
case DC_COMPLETE:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
myrpt->rem_dtmfbuf[0] = 0;
myrpt->rem_dtmfidx = -1;
myrpt->rem_dtmf_time = 0;
@@ -3170,14 +4092,14 @@ static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
od = *data++;
for(j = 0 ; j < 8 ; j++){
d = od & 1;
- outb(d,myrpt->iobase);
+ outb(d,myrpt->p.iobase);
/* >= 15 us */
for(delayvar = 1; delayvar < 15000; delayvar++);
od >>= 1;
- outb(d | 2,myrpt->iobase);
+ outb(d | 2,myrpt->p.iobase);
/* >= 30 us */
for(delayvar = 1; delayvar < 30000; delayvar++);
- outb(d,myrpt->iobase);
+ outb(d,myrpt->p.iobase);
/* >= 10 us */
for(delayvar = 1; delayvar < 10000; delayvar++);
}
@@ -3799,6 +4721,7 @@ static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
static int setrem(struct rpt *myrpt)
{
+ return 0; /* XXX BROKEN!! */
if(!strcmp(myrpt->remote, remote_rig_ft897))
return set_ft897(myrpt);
else if(!strcmp(myrpt->remote, remote_rig_rbi))
@@ -3809,6 +4732,7 @@ static int setrem(struct rpt *myrpt)
static int closerem(struct rpt *myrpt)
{
+ return 0; /* XXX BROKEN!! */
if(!strcmp(myrpt->remote, remote_rig_ft897))
return closerem_ft897(myrpt);
else
@@ -4030,7 +4954,7 @@ static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int c
return DC_ERROR;
}
- val = ast_variable_retrieve(cfg, myrpt->memory, digitbuf);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, digitbuf);
if (!val){
if (ast_safe_sleep(mychannel,1000) == -1)
return DC_ERROR;
@@ -4717,7 +5641,7 @@ int ret,res = 0,src;
if (myrpt->dtmfidx == -1)
{
/* if not lead-in digit, dont worry */
- if (c != myrpt->funcchar) return 0;
+ if (c != myrpt->p.funcchar) return 0;
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = now;
@@ -4730,11 +5654,11 @@ int ret,res = 0,src;
myrpt->dtmfbuf[0] = 0;
myrpt->dtmf_time_rem = now;
}
- if (c == myrpt->funcchar)
+ if (c == myrpt->p.funcchar)
{
/* if star at beginning, or 2 together, erase buffer */
if ((myrpt->dtmfidx < 1) ||
- (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->funcchar))
+ (myrpt->dtmfbuf[myrpt->dtmfidx - 1] == myrpt->p.funcchar))
{
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[0] = 0;
@@ -4771,6 +5695,10 @@ int ret,res = 0,src;
case DC_COMPLETE:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, myrpt->dtmfbuf, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
myrpt->dtmfbuf[0] = 0;
myrpt->dtmfidx = -1;
myrpt->dtmf_time_rem = 0;
@@ -4819,7 +5747,7 @@ int seq,res;
ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
}
if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
- res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
+ res = telem_lookup(myrpt,myrpt->remchannel, myrpt->name, "functcomplete");
rmt_telem_finish(myrpt,myrpt->remchannel);
return res;
}
@@ -4829,7 +5757,7 @@ static int handle_remote_phone_dtmf(struct rpt *myrpt, char c, char *keyed, int
int res;
- if (keyed && *keyed && (c == myrpt->endchar))
+ if (keyed && *keyed && (c == myrpt->p.endchar))
{
*keyed = 0;
return DC_INDETERMINATE;
@@ -4845,7 +5773,7 @@ int res;
ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
}
if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
- res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
+ res = telem_lookup(myrpt,myrpt->remchannel, myrpt->name, "functcomplete");
rmt_telem_finish(myrpt,myrpt->remchannel);
return res;
}
@@ -4855,7 +5783,7 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
char *val, *s, *s1, *s2, *tele;
char tmp[300], deststr[300] = "";
- val = ast_variable_retrieve(cfg, myrpt->nodes, l->name);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, l->name);
if (!val)
{
fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
@@ -4878,6 +5806,7 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
}
*tele++ = 0;
l->elaptime = 0;
+ l->connecttime = 0;
l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
if (l->chan){
ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
@@ -4902,7 +5831,7 @@ static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
return -1;
}
rpt_mutex_lock(&myrpt->lock);
- /* put back in queue queue */
+ /* put back in queue */
insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
rpt_mutex_unlock(&myrpt->lock);
ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
@@ -4916,10 +5845,10 @@ int res;
pthread_attr_t attr;
char cmd[MAXDTMF+1] = "";
- if (c == myrpt->endchar)
+ if (c == myrpt->p.endchar)
{
/* if in simple mode, kill autopatch */
- if (myrpt->simple && myrpt->callmode)
+ if (myrpt->p.simple && myrpt->callmode)
{
rpt_mutex_lock(&myrpt->lock);
myrpt->callmode = 0;
@@ -4946,9 +5875,9 @@ char cmd[MAXDTMF+1] = "";
send_link_dtmf(myrpt,c);
return;
}
- if (!myrpt->simple)
+ if (!myrpt->p.simple)
{
- if (c == myrpt->funcchar)
+ if (c == myrpt->p.funcchar)
{
myrpt->dtmfidx = 0;
myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
@@ -4956,7 +5885,7 @@ char cmd[MAXDTMF+1] = "";
time(&myrpt->dtmf_time);
return;
}
- else if ((c != myrpt->endchar) && (myrpt->dtmfidx >= 0))
+ else if ((c != myrpt->p.endchar) && (myrpt->dtmfidx >= 0))
{
time(&myrpt->dtmf_time);
@@ -4978,6 +5907,10 @@ char cmd[MAXDTMF+1] = "";
myrpt->dtmfbuf[0] = 0;
break;
case DC_COMPLETE:
+ myrpt->totalexecdcommands++;
+ myrpt->dailyexecdcommands++;
+ strncpy(myrpt->lastdtmfcommand, cmd, MAXDTMF-1);
+ myrpt->lastdtmfcommand[MAXDTMF-1] = '\0';
myrpt->dtmfbuf[0] = 0;
myrpt->dtmfidx = -1;
myrpt->dtmf_time = 0;
@@ -4999,9 +5932,14 @@ char cmd[MAXDTMF+1] = "";
}
else /* if simple */
{
- if ((!myrpt->callmode) && (c == myrpt->funcchar))
+ if ((!myrpt->callmode) && (c == myrpt->p.funcchar))
{
myrpt->callmode = 1;
+ myrpt->patchnoct = 0;
+ myrpt->patchquiet = 0;
+ myrpt->patchfarenddisconnect = 0;
+ myrpt->patchdialtime = 0;
+ strncpy(myrpt->patchcontext, myrpt->p.ourcontext, MAXPATCHCONTEXT);
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
rpt_mutex_unlock(&myrpt->lock);
@@ -5016,15 +5954,16 @@ char cmd[MAXDTMF+1] = "";
myrpt->exten[myrpt->cidx++] = c;
myrpt->exten[myrpt->cidx] = 0;
/* if this exists */
- if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ if (ast_exists_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
{
myrpt->callmode = 2;
rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt,PROC,NULL);
+ if(!myrpt->patchquiet)
+ rpt_telemetry(myrpt,PROC,NULL);
return;
}
/* if can continue, do so */
- if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+ if (!ast_canmatch_extension(myrpt->pchannel,myrpt->patchcontext,myrpt->exten,1,NULL))
{
/* call has failed, inform user */
myrpt->callmode = 4;
@@ -5046,19 +5985,48 @@ char cmd[MAXDTMF+1] = "";
static void queue_id(struct rpt *myrpt)
{
myrpt->mustid = myrpt->tailid = 0;
- myrpt->idtimer = myrpt->idtime; /* Reset our ID timer */
+ myrpt->idtimer = myrpt->p.idtime; /* Reset our ID timer */
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt,ID,NULL);
rpt_mutex_lock(&myrpt->lock);
}
+/* Scheduler */
+
+static void do_scheduler(struct rpt *myrpt)
+{
+ int res;
+ struct tm tmnow;
+
+ memcpy(&myrpt->lasttv, &myrpt->curtv, sizeof(struct timeval));
+
+ if( (res = gettimeofday(&myrpt->curtv, NULL)) < 0)
+ ast_log(LOG_NOTICE, "Scheduler gettime of day returned: %s\n", strerror(res));
+
+ /* Try to get close to a 1 second resolution */
+
+ if(myrpt->lasttv.tv_sec == myrpt->curtv.tv_sec)
+ return;
+
+ ast_localtime(&myrpt->curtv.tv_sec, &tmnow, NULL);
+
+ /* If midnight, then reset all daily statistics */
+
+ if((tmnow.tm_hour == 0)&&(tmnow.tm_min == 0)&&(tmnow.tm_sec == 0)){
+ myrpt->dailykeyups = 0;
+ myrpt->dailytxtime = 0;
+ myrpt->dailykerchunks = 0;
+ myrpt->dailyexecdcommands = 0;
+ }
+}
+
/* single thread with one file (request) to dial */
static void *rpt(void *this)
{
struct rpt *myrpt = (struct rpt *)this;
char *tele,*idtalkover,c;
-int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,nonidentqueued,tailmessagequeued,ctqueued;
+int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,othertelemqueued,tailmessagequeued,ctqueued;
struct ast_channel *who;
ZT_CONFINFO ci; /* conference info */
time_t t;
@@ -5066,13 +6034,30 @@ struct rpt_link *l,*m;
struct rpt_tele *telem;
char tmpstr[300];
+ rpt_mutex_lock(&myrpt->lock);
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
+ telem = telem->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+ /* find our index, and load the vars initially */
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
+ break;
+ }
+ }
rpt_mutex_lock(&myrpt->lock);
strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
tele = strchr(tmpstr,'/');
if (!tele)
{
- fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
+ fprintf(stderr,"rpt:Rxchannel Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
rpt_mutex_unlock(&myrpt->lock);
myrpt->rpt_thread = AST_PTHREADT_STOP;
pthread_exit(NULL);
@@ -5119,7 +6104,7 @@ char tmpstr[300];
tele = strchr(tmpstr,'/');
if (!tele)
{
- fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
+ fprintf(stderr,"rpt:Txchannel Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
rpt_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
myrpt->rpt_thread = AST_PTHREADT_STOP;
@@ -5204,7 +6189,7 @@ char tmpstr[300];
/* make a conference for the pseudo */
ci.chan = 0;
ci.confno = -1; /* make a new conf */
- ci.confmode = (myrpt->duplex == 2) ? ZT_CONF_CONFANNMON :
+ ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
(ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
/* first put the channel on the conference in announce mode */
if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1)
@@ -5257,16 +6242,18 @@ char tmpstr[300];
myrpt->links.prev = &myrpt->links;
myrpt->tailtimer = 0;
myrpt->totimer = 0;
- myrpt->tmsgtimer = myrpt->tailmessagetime;
- myrpt->idtimer = myrpt->politeid;
+ myrpt->tmsgtimer = myrpt->p.tailmessagetime;
+ myrpt->idtimer = myrpt->p.politeid;
myrpt->mustid = myrpt->tailid = 0;
myrpt->callmode = 0;
myrpt->tounkeyed = 0;
myrpt->tonotify = 0;
myrpt->retxtimer = 0;
+ myrpt->skedtimer = 0;
+ myrpt->tailevent = 0;
lasttx = 0;
myrpt->keyed = 0;
- idtalkover = ast_variable_retrieve(cfg, myrpt->name, "idtalkover");
+ idtalkover = ast_variable_retrieve(myrpt->cfg, myrpt->name, "idtalkover");
myrpt->dtmfidx = -1;
myrpt->dtmfbuf[0] = 0;
myrpt->rem_dtmfidx = -1;
@@ -5275,9 +6262,21 @@ char tmpstr[300];
myrpt->rem_dtmf_time = 0;
myrpt->enable = 1;
myrpt->disgorgetime = 0;
- if (myrpt->startupmacro)
+ myrpt->lastnodewhichkeyedusup[0] = '\0';
+ myrpt->dailytxtime = 0;
+ myrpt->totaltxtime = 0;
+ myrpt->dailykeyups = 0;
+ myrpt->totalkeyups = 0;
+ myrpt->dailykerchunks = 0;
+ myrpt->totalkerchunks = 0;
+ myrpt->dailyexecdcommands = 0;
+ myrpt->totalexecdcommands = 0;
+ myrpt->timeouts = 0;
+ myrpt->exten[0] = '\0';
+ myrpt->lastdtmfcommand[0] = '\0';
+ if (myrpt->p.startupmacro)
{
- snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->startupmacro);
+ snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
}
rpt_mutex_unlock(&myrpt->lock);
val = 0;
@@ -5313,8 +6312,7 @@ char tmpstr[300];
ast_log(LOG_NOTICE,"myrpt->retxtimer = %ld\n",myrpt->retxtimer);
ast_log(LOG_NOTICE,"myrpt->totimer = %d\n",myrpt->totimer);
ast_log(LOG_NOTICE,"myrpt->tailtimer = %d\n",myrpt->tailtimer);
- ast_log(LOG_NOTICE,"myrpt->mustid = %d\n",myrpt->mustid);
- ast_log(LOG_NOTICE,"myrpt->tailid = %d\n",myrpt->tailid);
+ ast_log(LOG_NOTICE,"myrpt->tailevent = %d\n",myrpt->tailevent);
zl = myrpt->links.next;
while(zl != &myrpt->links){
@@ -5329,7 +6327,7 @@ char tmpstr[300];
ast_log(LOG_NOTICE," link->disctime %ld\n",zl->disctime);
ast_log(LOG_NOTICE," link->retrytimer %ld\n",zl->retrytimer);
ast_log(LOG_NOTICE," link->retries = %d\n",zl->retries);
-
+ ast_log(LOG_NOTICE," link->reconnects = %d\n",zl->reconnects);
zl = zl->next;
}
@@ -5345,98 +6343,122 @@ char tmpstr[300];
}
+ if (myrpt->reload)
+ {
+ struct rpt_tele *telem;
+
+ rpt_mutex_lock(&myrpt->lock);
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
+ telem = telem->next;
+ }
+ myrpt->reload = 0;
+ rpt_mutex_unlock(&myrpt->lock);
+ usleep(10000);
+ /* find our index, and load the vars */
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
+ break;
+ }
+ }
+ }
+
rpt_mutex_lock(&myrpt->lock);
if (ast_check_hangup(myrpt->rxchannel)) break;
if (ast_check_hangup(myrpt->txchannel)) break;
if (ast_check_hangup(myrpt->pchannel)) break;
if (ast_check_hangup(myrpt->txpchannel)) break;
+
+ /* Update local tx with keyed if not parsing a command */
myrpt->localtx = myrpt->keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]);
-
/* If someone's connected, and they're transmitting from their end to us, set remrx true */
-
l = myrpt->links.next;
remrx = 0;
while(l != &myrpt->links)
{
- if (l->lastrx) remrx = 1;
+ if (l->lastrx){
+ remrx = 1;
+ if(l->name[0] != '0') /* Ignore '0' nodes */
+ strcpy(myrpt->lastnodewhichkeyedusup, l->name); /* Note the node which is doing the key up */
+ }
l = l->next;
}
-
- /* Create a "must_id" flag for the cleanup ID */
-
+ /* Create a "must_id" flag for the cleanup ID */
myrpt->mustid |= (myrpt->idtimer) && (myrpt->keyed || remrx) ;
-
/* Build a fresh totx from myrpt->keyed and autopatch activated */
-
totx = myrpt->callmode;
- if (myrpt->duplex > 1) totx = totx || myrpt->localtx;
-
- /* Traverse the telemetry list to see if there's an ID queued and if there is not an ID queued */
-
+ /* If full duplex, add local tx to totx */
+ if (myrpt->p.duplex > 1) totx = totx || myrpt->localtx;
+ /* Traverse the telemetry list to see what's queued */
identqueued = 0;
- nonidentqueued = 0;
+ othertelemqueued = 0;
tailmessagequeued = 0;
ctqueued = 0;
telem = myrpt->tele.next;
while(telem != &myrpt->tele)
{
if((telem->mode == ID) || (telem->mode == IDTALKOVER)){
- identqueued = 1;
+ identqueued = 1; /* Identification telemetry */
}
else if(telem->mode == TAILMSG)
{
- tailmessagequeued = 1;
+ tailmessagequeued = 1; /* Tail message telemetry */
}
else
{
if (telem->mode != UNKEY)
- nonidentqueued = 1;
+ othertelemqueued = 1; /* Other telemetry */
else
- ctqueued = 1;
+ ctqueued = 1; /* Courtesy tone telemetry */
}
telem = telem->next;
}
- /* Add in any non-id telemetry */
-
- if (myrpt->duplex > 0) totx = totx || nonidentqueued;
-
- /* Update external transmitter PTT state with everything but ID telemetry */
-
+ /* Add in any "other" telemetry, if 3/4 or full duplex */
+ if (myrpt->p.duplex > 0) totx = totx || othertelemqueued;
+ /* Update external (to links) transmitter PTT state with everything but ID, CT, and tailmessage telemetry */
myrpt->exttx = totx;
- if (myrpt->duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
-
+ /* If half or 3/4 duplex, add localtx to external link tx */
+ if (myrpt->p.duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx;
/* Add in ID telemetry to local transmitter */
totx = totx || remrx;
- if (myrpt->duplex > 0)
+ /* If 3/4 or full duplex, add in ident and CT telemetry */
+ if (myrpt->p.duplex > 0)
totx = totx || identqueued || ctqueued;
+ /* Reset time out timer variables if there is no activity */
if (!totx)
{
- myrpt->totimer = myrpt->totime;
+ myrpt->totimer = myrpt->p.totime;
myrpt->tounkeyed = 0;
myrpt->tonotify = 0;
}
else
- myrpt->tailtimer = myrpt->hangtime; /* Initialize tail timer */
-
+ myrpt->tailtimer = myrpt->p.hangtime; /* Initialize tail timer */
+ /* Disable the local transmitter if we are timed out */
totx = totx && myrpt->totimer;
/* if timed-out and not said already, say it */
if ((!myrpt->totimer) && (!myrpt->tonotify))
{
myrpt->tonotify = 1;
+ myrpt->timeouts++;
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt,TIMEOUT,NULL);
rpt_mutex_lock(&myrpt->lock);
}
- /* if wants to transmit and in phone call, but timed out,
- reset time-out timer if keyed */
+
+ /* If unkey and re-key, reset time out timer */
if ((!totx) && (!myrpt->totimer) && (!myrpt->tounkeyed) && (!myrpt->keyed))
{
myrpt->tounkeyed = 1;
}
if ((!totx) && (!myrpt->totimer) && myrpt->tounkeyed && myrpt->keyed)
{
- myrpt->totimer = myrpt->totime;
+ myrpt->totimer = myrpt->p.totime;
myrpt->tounkeyed = 0;
myrpt->tonotify = 0;
rpt_mutex_unlock(&myrpt->lock);
@@ -5477,35 +6499,42 @@ char tmpstr[300];
/* If within 30 seconds of the time to ID, try do it in the tail */
/* else if at ID time limit, do it right over the top of them */
/* Lastly, if the repeater has been keyed, and the ID timer is expired, do a clean up ID */
-
-/* if (((totx && (!myrpt->exttx) && (myrpt->idtimer <= myrpt->politeid) && myrpt->tailtimer)) ||
- (myrpt->mustid && (!myrpt->idtimer)))
- {
- myrpt->mustid = 0;
- myrpt->idtimer = myrpt->idtime;
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt,ID,NULL);
- rpt_mutex_lock(&myrpt->lock);
- }
-*/
-
if(myrpt->mustid && (!myrpt->idtimer))
queue_id(myrpt);
if ((totx && (!myrpt->exttx) &&
- (myrpt->idtimer <= myrpt->politeid) && myrpt->tailtimer))
+ (myrpt->idtimer <= myrpt->p.politeid) && myrpt->tailtimer))
{
myrpt->tailid = 1;
}
+ /* If tail timer expires, then check for tail messages */
+ if(myrpt->tailevent){
+ myrpt->tailevent = 0;
+ if(myrpt->tailid){
+ totx = 1;
+ queue_id(myrpt);
+ }
+ else if ((myrpt->p.tailmessages[0]) &&
+ (myrpt->p.tailmessagetime) && (myrpt->tmsgtimer == 0)){
+ totx = 1;
+ myrpt->tmsgtimer = myrpt->p.tailmessagetime;
+ rpt_mutex_unlock(&myrpt->lock);
+ rpt_telemetry(myrpt, TAILMSG, NULL);
+ rpt_mutex_lock(&myrpt->lock);
+ }
+ }
+ /* Main TX control */
/* let telemetry transmit anyway (regardless of timeout) */
- if (myrpt->duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
+ if (myrpt->p.duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele);
if (totx && (!lasttx))
{
lasttx = 1;
+ myrpt->dailykeyups++;
+ myrpt->totalkeyups++;
rpt_mutex_unlock(&myrpt->lock);
ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_KEY);
rpt_mutex_lock(&myrpt->lock);
@@ -5531,8 +6560,9 @@ char tmpstr[300];
myrpt->rem_dtmfidx = -1;
myrpt->rem_dtmfbuf[0] = 0;
}
-
- /* Reconnect kludge */
+
+ /* Reconnect */
+
l = myrpt->links.next;
while(l != &myrpt->links)
{
@@ -5586,7 +6616,6 @@ char tmpstr[300];
if (l->chan) ast_indicate(l->chan,AST_CONTROL_RADIO_UNKEY);
}
} else l->retxtimer = 0;
-#ifdef RECONNECT_KLUDGE
if (l->disctime) /* Disconnect timer active on a channel ? */
{
l->disctime -= elap;
@@ -5599,7 +6628,10 @@ char tmpstr[300];
l->retrytimer -= elap;
if (l->retrytimer < 0) l->retrytimer = 0;
}
-#endif
+
+ /* Tally connect time */
+ l->connecttime += elap;
+
/* ignore non-timing channels */
if (l->elaptime < 0)
{
@@ -5614,13 +6646,9 @@ char tmpstr[300];
l->elaptime = 0;
rpt_mutex_unlock(&myrpt->lock);
if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
-#ifndef RECONNECT_KLUDGE
- rpt_telemetry(myrpt,CONNFAIL,l);
-#endif
rpt_mutex_lock(&myrpt->lock);
break;
}
-#ifdef RECONNECT_KLUDGE
if ((!l->chan) && (!l->retrytimer) && l->outbound &&
(l->retries++ < MAX_RETRIES) && (l->hasconnected))
{
@@ -5677,26 +6705,17 @@ char tmpstr[300];
rpt_mutex_lock(&myrpt->lock);
break;
}
-#endif
l = l->next;
}
+ if(totx){
+ myrpt->dailytxtime += elap;
+ myrpt->totaltxtime += elap;
+ }
i = myrpt->tailtimer;
if (myrpt->tailtimer) myrpt->tailtimer -= elap;
if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
-
- if((i) && (myrpt->tailtimer == 0)){
- if(myrpt->tailid){
- queue_id(myrpt);
- }
- else if ((myrpt->tailmessages[0]) &&
- (myrpt->tailmessagetime) && (myrpt->tmsgtimer == 0)){
- myrpt->tmsgtimer = myrpt->tailmessagetime;
- rpt_mutex_unlock(&myrpt->lock);
- rpt_telemetry(myrpt, TAILMSG, NULL);
- rpt_mutex_lock(&myrpt->lock);
- }
- }
- if (myrpt->tailtimer < 0) myrpt->tailtimer = 0;
+ if((i) && (myrpt->tailtimer == 0))
+ myrpt->tailevent = 1;
if (myrpt->totimer) myrpt->totimer -= elap;
if (myrpt->totimer < 0) myrpt->totimer = 0;
if (myrpt->idtimer) myrpt->idtimer -= elap;
@@ -5706,6 +6725,13 @@ char tmpstr[300];
/* do macro timers */
if (myrpt->macrotimer) myrpt->macrotimer -= elap;
if (myrpt->macrotimer < 0) myrpt->macrotimer = 0;
+ /* Execute scheduler appx. every 2 tenths of a second */
+ if (myrpt->skedtimer <= 0){
+ myrpt->skedtimer = 200;
+ do_scheduler(myrpt);
+ }
+ else
+ myrpt->skedtimer -=elap;
if (!ms)
{
rpt_mutex_unlock(&myrpt->lock);
@@ -5731,8 +6757,59 @@ char tmpstr[300];
}
if (f->frametype == AST_FRAME_VOICE)
{
- if (!myrpt->localtx)
+#ifdef _MDC_DECODE_H_
+ unsigned char ubuf[2560];
+ short *sp;
+ int n;
+#endif
+
+ if (!myrpt->localtx) {
memset(f->data,0,f->datalen);
+ }
+
+#ifdef _MDC_DECODE_H_
+ sp = (short *) f->data;
+ /* convert block to unsigned char */
+ for(n = 0; n < f->datalen / 2; n++)
+ {
+ ubuf[n] = (*sp++ >> 8) + 128;
+ }
+ n = mdc_decoder_process_samples(myrpt->mdc,ubuf,f->datalen / 2);
+ if (n == 1)
+ {
+ unsigned char op,arg;
+ unsigned short unitID;
+
+ mdc_decoder_get_packet(myrpt->mdc,&op,&arg,&unitID);
+ if (debug > 2)
+ {
+ ast_log(LOG_NOTICE,"Got (single-length) packet:\n");
+ ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
+ op & 255,arg & 255,unitID);
+ }
+ if ((op == 1) && (arg == 0))
+ {
+ myrpt->lastunit = unitID;
+ }
+ }
+ if ((debug > 2) && (i == 2))
+ {
+ unsigned char op,arg,ex1,ex2,ex3,ex4;
+ unsigned short unitID;
+
+ mdc_decoder_get_double_packet(myrpt->mdc,&op,&arg,&unitID,
+ &ex1,&ex2,&ex3,&ex4);
+ ast_log(LOG_NOTICE,"Got (double-length) packet:\n");
+ ast_log(LOG_NOTICE,"op: %02x, arg: %02x, UnitID: %04x\n",
+ op & 255,arg & 255,unitID);
+ ast_log(LOG_NOTICE,"ex1: %02x, ex2: %02x, ex3: %02x, ex4: %02x\n",
+ ex1 & 255, ex2 & 255, ex3 & 255, ex4 & 255);
+ }
+#endif
+#ifdef __RPT_NOTCH
+ /* apply inbound filters, if any */
+ rpt_filter(myrpt,f->data,f->datalen / 2);
+#endif
ast_write(myrpt->pchannel,f);
}
else if (f->frametype == AST_FRAME_DTMF)
@@ -5853,7 +6930,6 @@ char tmpstr[300];
f = ast_read(l->chan);
if (!f)
{
-#ifdef RECONNECT_KLUDGE
if ((!l->disced) && (!l->outbound))
{
if ((l->name[0] == '0') || l->isremote)
@@ -5884,7 +6960,6 @@ char tmpstr[300];
rpt_mutex_lock(&myrpt->lock);
break;
}
-#endif
rpt_mutex_lock(&myrpt->lock);
/* remove from queue */
remque((struct qelem *) l);
@@ -5926,7 +7001,10 @@ char tmpstr[300];
l->hasconnected = 1;
l->elaptime = -1;
l->retries = 0;
- if (!lconnected) rpt_telemetry(myrpt,CONNECTED,l);
+ if (!lconnected)
+ rpt_telemetry(myrpt,CONNECTED,l);
+ else
+ l->reconnects++;
}
/* if RX key */
if (f->subclass == AST_CONTROL_RADIO_KEY)
@@ -5943,7 +7021,6 @@ char tmpstr[300];
if (f->subclass == AST_CONTROL_HANGUP)
{
ast_frfree(f);
-#ifdef RECONNECT_KLUDGE
if ((!l->outbound) && (!l->disced))
{
if ((l->name[0] == '0') || l->isremote)
@@ -5973,7 +7050,6 @@ char tmpstr[300];
rpt_mutex_lock(&myrpt->lock);
break;
}
-#endif
rpt_mutex_lock(&myrpt->lock);
/* remove from queue */
remque((struct qelem *) l);
@@ -6075,187 +7151,56 @@ char tmpstr[300];
return NULL;
}
-
+
static void *rpt_master(void *ignore)
{
-char *this,*val;
-struct ast_variable *vp;
-int i,j,n,longestnode;
+int i,n;
pthread_attr_t attr;
+struct ast_config *cfg;
+char *this,*val;
- /* start with blank config */
- memset(&rpt_vars,0,sizeof(rpt_vars));
-
- cfg = ast_config_load("rpt.conf");
+ /* go thru all the specified repeaters */
+ this = NULL;
+ n = 0;
+ rpt_vars[n].cfg = ast_config_load("rpt.conf");
+ cfg = rpt_vars[n].cfg;
if (!cfg) {
ast_log(LOG_NOTICE, "Unable to open radio repeater configuration rpt.conf. Radio Repeater disabled.\n");
pthread_exit(NULL);
}
-
- /* go thru all the specified repeaters */
- this = NULL;
- n = 0;
while((this = ast_category_browse(cfg,this)) != NULL)
{
-
for(i = 0 ; i < strlen(this) ; i++){
if((this[i] < '0') || (this[i] > '9'))
break;
}
- if(i != strlen(this))
- continue; /* Not a node defn */
-
- ast_log(LOG_DEBUG,"Loading config for repeater %s\n",this);
+ if(i != strlen(this)) continue; /* Not a node defn */
+ memset(&rpt_vars[n],0,sizeof(rpt_vars[n]));
+ rpt_vars[n].name = strdup(this);
+ val = ast_variable_retrieve(cfg,this,"rxchannel");
+ if (val) rpt_vars[n].rxchanname = strdup(val);
+ val = ast_variable_retrieve(cfg,this,"txchannel");
+ if (val) rpt_vars[n].txchanname = strdup(val);
+ val = ast_variable_retrieve(cfg,this,"remote");
+ if (val) rpt_vars[n].remote = strdup(val);
ast_mutex_init(&rpt_vars[n].lock);
rpt_vars[n].tele.next = &rpt_vars[n].tele;
rpt_vars[n].tele.prev = &rpt_vars[n].tele;
rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
- rpt_vars[n].name = this;
- rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
- rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
- rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
- if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
- rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
- rpt_vars[n].acctcode = ast_variable_retrieve(cfg,this,"accountcode");
- rpt_vars[n].ident = ast_variable_retrieve(cfg,this,"idrecording");
- val = ast_variable_retrieve(cfg,this,"hangtime");
- if (val) rpt_vars[n].hangtime = atoi(val);
- else rpt_vars[n].hangtime = HANGTIME;
- val = ast_variable_retrieve(cfg,this,"totime");
- if (val) rpt_vars[n].totime = atoi(val);
- else rpt_vars[n].totime = TOTIME;
-
- rpt_vars[n].tailmessagetime = retrieve_astcfgint(this, "tailmessagetime", 0, 2400000, 0);
- rpt_vars[n].tailsquashedtime = retrieve_astcfgint(this, "tailsquashedtime", 0, 2400000, 0);
- rpt_vars[n].duplex = retrieve_astcfgint(this,"duplex",0,3,2);
- rpt_vars[n].idtime = retrieve_astcfgint( this, "idtime", 60000, 2400000, IDTIME); /* Enforce a min max */
- rpt_vars[n].politeid = retrieve_astcfgint( this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
- rpt_vars[n].remote = ast_variable_retrieve(cfg,this,"remote");
- rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
- rpt_vars[n].tailmessages[0] = 0;
- rpt_vars[n].tailmessagemax = 0;
rpt_vars[n].tailmessagen = 0;
- val = ast_variable_retrieve(cfg,this,"tailmessagelist");
- if (val) rpt_vars[n].tailmessagemax = finddelim(val,rpt_vars[n].tailmessages);
- val = ast_variable_retrieve(cfg,this,"memory");
- if (!val) val = MEMORY;
- rpt_vars[n].memory = val;
- val = ast_variable_retrieve(cfg,this,"macro");
- if (!val) val = MACRO;
- rpt_vars[n].macro = val;
- rpt_vars[n].startupmacro = ast_variable_retrieve(cfg,this,"startup_macro");
- val = ast_variable_retrieve(cfg,this,"iobase");
- /* do not use atoi() here, we need to be able to have
- the input specified in hex or decimal so we use
- sscanf with a %i */
- if ((!val) || (sscanf(val,"%i",&rpt_vars[n].iobase) != 1))
- rpt_vars[n].iobase = DEFAULT_IOBASE;
- rpt_vars[n].simple = 0;
- rpt_vars[n].functions = ast_variable_retrieve(cfg,this,"functions");
- if (!rpt_vars[n].functions)
- {
- rpt_vars[n].functions = FUNCTIONS;
- rpt_vars[n].simple = 1;
- }
- rpt_vars[n].link_functions = ast_variable_retrieve(cfg,this,"link_functions");
- if (!rpt_vars[n].link_functions)
- rpt_vars[n].link_functions = rpt_vars[n].functions;
- rpt_vars[n].phone_functions = ast_variable_retrieve(cfg,this,"phone_functions");
- rpt_vars[n].dphone_functions = ast_variable_retrieve(cfg,this,"dphone_functions");
- val = ast_variable_retrieve(cfg,this,"funcchar");
- if (!val) rpt_vars[n].funcchar = FUNCCHAR; else
- rpt_vars[n].funcchar = *val;
- val = ast_variable_retrieve(cfg,this,"endchar");
- if (!val) rpt_vars[n].endchar = ENDCHAR; else
- rpt_vars[n].endchar = *val;
- val = ast_variable_retrieve(cfg,this,"nobusyout");
- if (val) rpt_vars[n].nobusyout = ast_true(val);
- rpt_vars[n].nodes = ast_variable_retrieve(cfg,this,"nodes");
- if (!rpt_vars[n].nodes)
- rpt_vars[n].nodes = NODES;
+#ifdef _MDC_DECODE_H_
+ rpt_vars[n].mdc = mdc_decoder_new(8000);
+#endif
n++;
}
nrpts = n;
- ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);
+ ast_config_destroy(cfg);
+
/* start em all */
for(i = 0; i < n; i++)
{
+ load_rpt_vars(i,1);
- /*
- * Go through the node list to determine the longest node
- */
- longestnode = 0;
-
- vp = ast_variable_browse(cfg, rpt_vars[i].nodes);
-
- while(vp){
- j = strlen(vp->name);
- if (j > longestnode)
- longestnode = j;
- vp = vp->next;
- }
-
-
- rpt_vars[i].longestnode = longestnode;
-
- /*
- * For this repeater, Determine the length of the longest function
- */
- rpt_vars[i].longestfunc = 0;
- vp = ast_variable_browse(cfg, rpt_vars[i].functions);
- while(vp){
- j = strlen(vp->name);
- if (j > rpt_vars[i].longestfunc)
- rpt_vars[i].longestfunc = j;
- vp = vp->next;
- }
- /*
- * For this repeater, Determine the length of the longest function
- */
- rpt_vars[i].link_longestfunc = 0;
- vp = ast_variable_browse(cfg, rpt_vars[i].link_functions);
- while(vp){
- j = strlen(vp->name);
- if (j > rpt_vars[i].link_longestfunc)
- rpt_vars[i].link_longestfunc = j;
- vp = vp->next;
- }
- rpt_vars[i].phone_longestfunc = 0;
- if (rpt_vars[i].phone_functions)
- {
- vp = ast_variable_browse(cfg, rpt_vars[i].phone_functions);
- while(vp){
- j = strlen(vp->name);
- if (j > rpt_vars[i].phone_longestfunc)
- rpt_vars[i].phone_longestfunc = j;
- vp = vp->next;
- }
- }
- rpt_vars[i].dphone_longestfunc = 0;
- if (rpt_vars[i].dphone_functions)
- {
- vp = ast_variable_browse(cfg, rpt_vars[i].dphone_functions);
- while(vp){
- j = strlen(vp->name);
- if (j > rpt_vars[i].dphone_longestfunc)
- rpt_vars[i].dphone_longestfunc = j;
- vp = vp->next;
- }
- }
- rpt_vars[i].macro_longest = 1;
- vp = ast_variable_browse(cfg, rpt_vars[i].macro);
- while(vp){
- j = strlen(vp->name);
- if (j > rpt_vars[i].macro_longest)
- rpt_vars[i].macro_longest = j;
- vp = vp->next;
- }
- if (!rpt_vars[i].rxchanname)
- {
- ast_log(LOG_WARNING,"Did not specify rxchanname for node %s\n",rpt_vars[i].name);
- ast_config_destroy(cfg);
- pthread_exit(NULL);
- }
/* if is a remote, dont start one for it */
if (rpt_vars[i].remote)
{
@@ -6268,7 +7213,7 @@ pthread_attr_t attr;
rpt_vars[i].powerlevel = REM_MEDPWR;
continue;
}
- if (!rpt_vars[i].ident)
+ if (!rpt_vars[i].p.ident)
{
ast_log(LOG_WARNING,"Did not specify ident for node %s\n",rpt_vars[i].name);
ast_config_destroy(cfg);
@@ -6392,7 +7337,7 @@ static int rpt_exec(struct ast_channel *chan, void *data)
m = myrpt->callmode;
rpt_mutex_unlock(&myrpt->lock);
- if ((!myrpt->nobusyout) && m)
+ if ((!myrpt->p.nobusyout) && m)
{
if (chan->_state != AST_STATE_UP)
{
@@ -6457,9 +7402,13 @@ static int rpt_exec(struct ast_channel *chan, void *data)
}
/* At this point we have a priority and maybe an extension and a context */
chan->priority = atoi(priority);
- if (exten)
+#ifdef OLD_ASTERISK
+ if(exten && strcasecmp(exten, "BYEXTENSION"))
+#else
+ if(exten)
+#endif
strncpy(chan->exten, exten, sizeof(chan->exten)-1);
- if (context)
+ if(context)
strncpy(chan->context, context, sizeof(chan->context)-1);
} else { /* increment the priority by default*/
chan->priority++;
@@ -6528,7 +7477,7 @@ static int rpt_exec(struct ast_channel *chan, void *data)
/* look for his reported node string */
- val = ast_variable_retrieve(cfg, myrpt->nodes, b1);
+ val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, b1);
if (!val)
{
ast_log(LOG_WARNING, "Reported node %s cannot be found!!\n",b1);
@@ -6580,6 +7529,7 @@ static int rpt_exec(struct ast_channel *chan, void *data)
{
char *b,*b1;
+ int reconnects = 0;
/* look at callerid to see what node this comes from */
if (!chan->cid.cid_num) /* if doesn't have caller id */
@@ -6615,6 +7565,8 @@ static int rpt_exec(struct ast_channel *chan, void *data)
l->killme = 1;
l->retries = MAX_RETRIES + 1;
l->disced = 2;
+ reconnects = l->reconnects;
+ reconnects++;
rpt_mutex_unlock(&myrpt->lock);
usleep(500000);
} else
@@ -6634,6 +7586,7 @@ static int rpt_exec(struct ast_channel *chan, void *data)
l->chan = chan;
l->connected = 1;
l->hasconnected = 1;
+ l->reconnects = reconnects;
l->phonemode = phone_mode;
ast_set_read_format(l->chan,AST_FORMAT_SLINEAR);
ast_set_write_format(l->chan,AST_FORMAT_SLINEAR);
@@ -6680,13 +7633,24 @@ static int rpt_exec(struct ast_channel *chan, void *data)
rpt_mutex_lock(&myrpt->lock);
}
myrpt->remoteon = 1;
- if (ioperm(myrpt->iobase,1,1) == -1)
+ if (ioperm(myrpt->p.iobase,1,1) == -1)
{
rpt_mutex_unlock(&myrpt->lock);
- ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->iobase);
+ ast_log(LOG_WARNING, "Cant get io permission on IO port %x hex\n",myrpt->p.iobase);
return -1;
}
LOCAL_USER_ADD(u);
+ rpt_mutex_unlock(&myrpt->lock);
+ /* find our index, and load the vars initially */
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
+ break;
+ }
+ }
+ rpt_mutex_lock(&myrpt->lock);
tele = strchr(myrpt->rxchanname,'/');
if (!tele)
{
@@ -6765,11 +7729,12 @@ static int rpt_exec(struct ast_channel *chan, void *data)
myrpt->dtmf_time_rem = 0;
myrpt->hfscanmode = 0;
myrpt->hfscanstatus = 0;
- if (myrpt->startupmacro)
+ if (myrpt->p.startupmacro)
{
myrpt->remchannel = chan; /* Save copy of channel */
- snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->startupmacro);
+ snprintf(myrpt->macrobuf,MAXMACRO - 1,"PPPP%s",myrpt->p.startupmacro);
}
+ myrpt->reload = 0;
rpt_mutex_unlock(&myrpt->lock);
setrem(myrpt);
ast_set_write_format(chan, AST_FORMAT_SLINEAR);
@@ -6801,6 +7766,21 @@ static int rpt_exec(struct ast_channel *chan, void *data)
{
if (ast_check_hangup(chan)) break;
if (ast_check_hangup(myrpt->rxchannel)) break;
+ if (myrpt->reload)
+ {
+ myrpt->reload = 0;
+ rpt_mutex_unlock(&myrpt->lock);
+ /* find our index, and load the vars */
+ for(i = 0; i < nrpts; i++)
+ {
+ if (&rpt_vars[i] == myrpt)
+ {
+ load_rpt_vars(i,0);
+ break;
+ }
+ }
+ rpt_mutex_lock(&myrpt->lock);
+ }
ms = MSWAIT;
who = ast_waitfor_n(cs,n,&ms);
if (who == NULL) ms = 0;
@@ -7028,13 +8008,17 @@ static int rpt_exec(struct ast_channel *chan, void *data)
return res;
}
-static int unload_module(void *mod)
+#ifdef OLD_ASTERISK
+int unload_module()
+#else
+static int unload_module(void* mod)
+#endif
{
int i;
STANDARD_HANGUP_LOCALUSERS;
for(i = 0; i < nrpts; i++) {
- if (!strcmp(rpt_vars[i].name,rpt_vars[i].nodes)) continue;
+ if (!strcmp(rpt_vars[i].name,rpt_vars[i].p.nodes)) continue;
ast_mutex_destroy(&rpt_vars[i].lock);
}
i = ast_unregister_application(app);
@@ -7042,30 +8026,72 @@ static int unload_module(void *mod)
/* Unregister cli extensions */
ast_cli_unregister(&cli_debug);
ast_cli_unregister(&cli_dump);
+ ast_cli_unregister(&cli_stats);
+ ast_cli_unregister(&cli_lstats);
+ ast_cli_unregister(&cli_reload);
+ ast_cli_unregister(&cli_restart);
return i;
}
+#ifdef OLD_ASTERISK
+int load_module()
+#else
static int load_module(void *mod)
+#endif
{
ast_pthread_create(&rpt_master_thread,NULL,rpt_master,NULL);
/* Register cli extensions */
ast_cli_register(&cli_debug);
ast_cli_register(&cli_dump);
+ ast_cli_register(&cli_stats);
+ ast_cli_register(&cli_lstats);
+ ast_cli_register(&cli_reload);
+ ast_cli_register(&cli_restart);
return ast_register_application(app, rpt_exec, synopsis, descrip);
}
+#ifdef OLD_ASTERISK
+char *description()
+#else
static const char *description(void)
+#endif
{
return tdesc;
}
+#ifdef OLD_ASTERISK
+int usecount(void)
+{
+ int res;
+ STANDARD_USECOUNT(res);
+ return res;
+}
+#endif
+
+#ifdef OLD_ASTERISK
+char *key()
+#else
static const char *key(void)
+#endif
{
return ASTERISK_GPL_KEY;
}
-STD_MOD1;
+#ifdef OLD_ASTERISK
+int reload()
+#else
+static int reload(void *mod)
+#endif
+{
+int n;
+
+ for(n = 0; n < nrpts; n++) rpt_vars[n].reload = 1;
+ return(0);
+}
+#ifndef OLD_ASTERISK
+STD_MOD(MOD_1, reload, NULL, NULL);
+#endif