[asterisk-commits] branch bweschke/polycom_acd_functions r29967 - in
/team/bweschke/polycom_acd_...
asterisk-commits at lists.digium.com
asterisk-commits at lists.digium.com
Wed May 24 07:03:55 MST 2006
Author: bweschke
Date: Wed May 24 09:03:54 2006
New Revision: 29967
URL: http://svn.digium.com/view/asterisk?rev=29967&view=rev
Log:
Merged revisions 29903,29905,29935,29938 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk
........
r29903 | kpfleming | 2006-05-23 23:28:49 -0400 (Tue, 23 May 2006) | 4 lines
add a new option for 'obscuring' SIP user/peer names from fishers
use an enum for authentication results and clean up code
fix a bug where SUBSCRIBE for an unknown user/peer would not generate a response
........
r29905 | kpfleming | 2006-05-23 23:32:55 -0400 (Tue, 23 May 2006) | 2 lines
block SIP obscurity fix from merging... trunk version was different
........
r29935 | jdixon | 2006-05-24 03:01:02 -0400 (Wed, 24 May 2006) | 2 lines
Added incoming audio notch filtering, plus a bunch of command improvements, etc.
........
r29938 | crichter | 2006-05-24 03:58:52 -0400 (Wed, 24 May 2006) | 1 line
fixed to early connect bug which came in yesterday.., also added the transmit of progress indicators through channel vars
........
Modified:
team/bweschke/polycom_acd_functions/ (props changed)
team/bweschke/polycom_acd_functions/apps/app_rpt.c
team/bweschke/polycom_acd_functions/channels/chan_misdn.c
team/bweschke/polycom_acd_functions/channels/chan_sip.c
team/bweschke/polycom_acd_functions/configs/misdn.conf.sample
team/bweschke/polycom_acd_functions/configs/sip.conf.sample
Propchange: team/bweschke/polycom_acd_functions/
------------------------------------------------------------------------------
Binary property 'branch-1.2-blocked' - no diff available.
Propchange: team/bweschke/polycom_acd_functions/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Wed May 24 09:03:54 2006
@@ -1,1 +1,1 @@
-/trunk:1-29880
+/trunk:1-29966
Modified: team/bweschke/polycom_acd_functions/apps/app_rpt.c
URL: http://svn.digium.com/view/asterisk/team/bweschke/polycom_acd_functions/apps/app_rpt.c?rev=29967&r1=29966&r2=29967&view=diff
==============================================================================
--- team/bweschke/polycom_acd_functions/apps/app_rpt.c (original)
+++ team/bweschke/polycom_acd_functions/apps/app_rpt.c Wed May 24 09:03:54 2006
@@ -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 at 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{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 @@
#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 @@
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 @@
#define TOTIME 180000
#define IDTIME 300000
#define MAXRPTS 20
+#define MAX_STAT_LINKS 32
#define POLITEID 30000
#define FUNCTDELAY 1500
@@ -299,8 +331,22 @@
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
@@ -339,53 +385,77 @@
static struct rpt
{
+ ast_mutex_t lock;
+ struct ast_config *cfg;
+ char reload;
+
char *name;
- ast_mutex_t lock;
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 @@
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 @@
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 @@
/* 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 @@
"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 };
@@ -629,6 +735,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 @@
{"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[])
-{
-int i,inquo;
+
+
+static int finddelim(char *str, char *strp[], int limit)
+{
+int i,l,inquo;
inquo = 0;
i = 0;
@@ -695,7 +827,7 @@
strp[0] = 0;
return(0);
}
- for(; *str; str++)
+ for(l = 0; *str && (l < limit) ; str++)
{
if (*str == QUOTECHR)
{
@@ -713,6 +845,7 @@
if ((*str == DELIMCHR) && (!inquo))
{
*str = 0;
+ l++;
strp[i++] = str + 1;
}
}
@@ -721,6 +854,53 @@
}
+/*
+* 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;
@@ -729,6 +909,248 @@
/* leave this %i alone, non-base-10 input is useful here */
if (sscanf(str,"%i",&ret) != 1) return -1;
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);
}
/*
@@ -772,6 +1194,307 @@
ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
return RESULT_SUCCESS;
}
+ }
+ 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;
}
@@ -1054,27 +1777,7 @@
}
-/* 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 @@
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 @@
* 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 @@
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 @@
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 @@
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 @@
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 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 @@
/* 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 @@
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");
[... 2456 lines stripped ...]
More information about the asterisk-commits
mailing list