[asterisk-commits] jdixon: branch jdixon/chan_usbradio-1.4 r114639 - /team/jdixon/chan_usbradio-...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Apr 24 21:09:25 CDT 2008
Author: jdixon
Date: Thu Apr 24 21:09:22 2008
New Revision: 114639
URL: http://svn.digium.com/view/asterisk?view=rev&rev=114639
Log:
Updated to latest version (0.112)
Modified:
team/jdixon/chan_usbradio-1.4/apps/app_rpt.c
Modified: team/jdixon/chan_usbradio-1.4/apps/app_rpt.c
URL: http://svn.digium.com/view/asterisk/team/jdixon/chan_usbradio-1.4/apps/app_rpt.c?view=diff&rev=114639&r1=114638&r2=114639
==============================================================================
--- team/jdixon/chan_usbradio-1.4/apps/app_rpt.c (original)
+++ team/jdixon/chan_usbradio-1.4/apps/app_rpt.c Thu Apr 24 21:09:22 2008
@@ -1,9 +1,8 @@
/* #define OLD_ASTERISK */
-#define OLDKEY
/*
* Asterisk -- An open source telephony toolkit.
*
- * Copyright (C) 2002-2007, Jim Dixon, WB6NIL
+ * Copyright (C) 2002-2008, Jim Dixon, WB6NIL
*
* Jim Dixon, WB6NIL <jim at lambdatel.com>
* Serious contributions by Steve RoDgers, WA6ZFT <hwstar at rodgers.sdcoxmail.com>
@@ -21,12 +20,13 @@
/*! \file
*
* \brief Radio Repeater / Remote Base program
- * version 0.73 09/04/07
+ * version 0.112 4/13/08 2055 EDT
*
* \author Jim Dixon, WB6NIL <jim at lambdatel.com>
*
* \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar at rodgers.sdcoxmail.com>
- *
+ * \note Steven Henke, W9SH, <w9sh at arrl.net> added a few features here and there.
+ *
* See http://www.zapatatelephony.org/app_rpt.html
*
*
@@ -52,9 +52,11 @@
*
* status cmds:
*
- * 1 - Force ID
- * 2 - Give Time of Day
- * 3 - Give software Version
+ * 1 - Force ID (global)
+ * 2 - Give Time of Day (global)
+ * 3 - Give software Version (global)
+ * 11 - Force ID (local only)
+ * 12 - Give Time of Day (local only)
*
* cop (control operator) cmds:
*
@@ -78,6 +80,15 @@
* 18 - User functions (time, id, etc) disable
* 19 - Select alternate hang timer
* 20 - Select standard hang timer
+ * 21 - Enable Parrot Mode
+ * 22 - Disable Parrot Mode
+ * 23 - Birdbath (Current Parrot Cleanup/Flush)
+ * 24 - Flush all telemetry
+ * 25 - Query last node un-keyed
+ * 26 - Query all nodes keyed/unkeyed
+ * 30 - Recall Memory Setting in Attached Xcvr
+ * 31 - Channel Selector for Parallel Programmed Xcvr
+ * 32 - Touchtone pad test: command + Digit string + # to playback all digits pressed
*
* ilink cmds:
*
@@ -125,6 +136,9 @@
* 140 - Link Status (brief)
* 200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
*
+ * playback cmds:
+ * specify the name of the file to be played (for example, 25=rpt/foo)
+ *
*
* 'duplex' modes: (defaults to duplex=2)
*
@@ -152,15 +166,29 @@
/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
+#ifdef OLD_ASTERISK
+#define ast_free free
+#define ast_malloc malloc
+#define ast_strdup strdup
+#endif
+
+
#define MAXDTMF 32
#define MAXMACRO 2048
#define MAXLINKLIST 512
#define LINKLISTTIME 10000
#define LINKLISTSHORTTIME 200
+#define LINKPOSTTIME 30000
+#define LINKPOSTSHORTTIME 200
+#define KEYPOSTTIME 30000
+#define KEYPOSTSHORTTIME 200
#define MACROTIME 100
#define MACROPTIME 500
#define DTMF_TIMEOUT 3
#define KENWOOD_RETRIES 5
+#define TOPKEYN 32
+#define TOPKEYWAIT 3
+#define TOPKEYMAXSTR 30
#define AUTHTELLTIME 7000
#define AUTHTXTIME 1000
@@ -178,7 +206,15 @@
#define RETRY_TIMER_MS 5000
+#define PATCH_DIALPLAN_TIMEOUT 1500
+
+#ifdef OLD_ASTERISK
+#define START_DELAY 10
+#else
#define START_DELAY 2
+#endif
+
+#define RPT_LOCKOUT_SECS 10
#define MAXPEERSTR 31
#define MAXREMSTR 15
@@ -201,9 +237,14 @@
#define FUNCTIONS "functions"
#define TELEMETRY "telemetry"
#define MORSE "morse"
+#define TONEMACRO "tonemacro"
#define FUNCCHAR '*'
#define ENDCHAR '#'
#define EXTNODEFILE "/var/lib/asterisk/rpt_extnodes"
+#define NODENAMES "rpt/nodenames"
+#define PARROTFILE "/tmp/parrot_%s_%u"
+
+#define PARROTTIME 1000
#define DEFAULT_IOBASE 0x378
@@ -212,6 +253,10 @@
#define MAXCONNECTTIME 5000
#define MAXNODESTR 300
+
+#define MAXNODELEN 16
+
+#define MAXIDENTLEN 32
#define MAXPATCHCONTEXT 100
@@ -226,17 +271,29 @@
#define IC706_PL_MEMORY_OFFSET 50
+#define VOX_ON_DEBOUNCE_COUNT 3
+#define VOX_OFF_DEBOUNCE_COUNT 20
+#define VOX_MAX_THRESHOLD 10000.0
+#define VOX_MIN_THRESHOLD 3000.0
+#define VOX_TIMEOUT_MS 5000
+#define VOX_RECOVER_MS 500
+#define SIMPLEX_PATCH_DELAY 25
+#define SIMPLEX_PHONE_DELAY 25
+
+#define STATPOST_PROGRAM "/usr/bin/wget,-q,--output-document=/dev/null,--no-check-certificate"
+
#define ALLOW_LOCAL_CHANNELS
enum {REM_OFF,REM_MONITOR,REM_TX};
enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO,
- CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME,
+ CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, PLAYBACK,
STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH,
TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY, FULLSTATUS,
MEMNOTFOUND, INVFREQ, REMMODE, REMLOGIN, REMXXX, REMSHORTSTATUS,
- REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE,
- TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX};
+ REMLONGSTATUS, LOGINREQ, SCAN, SCANSTAT, TUNE, SETREMOTE, TOPKEY,
+ TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
+ STATS_TIME_LOCAL};
enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
@@ -245,9 +302,9 @@
enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE, DC_COMPLETEQUIET, DC_DOKEY};
-enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE};
-
-enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY};
+enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT, SOURCE_PHONE, SOURCE_DPHONE, SOURCE_ALT};
+
+enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM, DLY_COMP, DLY_LINKUNKEY, DLY_PARROT};
enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM};
@@ -303,6 +360,7 @@
#include "asterisk/localtime.h"
#include "asterisk/cdr.h"
#include "asterisk/options.h"
+#include "asterisk/manager.h"
#include <termios.h>
/* Start a tone-list going */
@@ -310,14 +368,15 @@
/*! Stop the tones from playing */
void ast_playtones_stop(struct ast_channel *chan);
-static char *tdesc = "Radio Repeater / Remote Base version 0.73 09/04/2007";
+static char *tdesc = "Radio Repeater / Remote Base version 0.112 4/13/2008";
static char *app = "Rpt";
static char *synopsis = "Radio Repeater/Remote Base Control System";
static char *descrip =
-" Rpt(nodename[|options]): Radio Remote Link or Remote Base Link Endpoint Process.\n"
+" Rpt(nodename[|options][|M][|*]): \n"
+" Radio Remote Link or Remote Base Link Endpoint Process.\n"
"\n"
" Not specifying an option puts it in normal endpoint mode (where source\n"
" IP and nodename are verified).\n"
@@ -349,7 +408,27 @@
" this mode), the 'dphone_functions' parameter must be specified\n"
" for the node in 'rpt.conf'. Otherwise no DTMF control will be\n"
" available to the phone user.\n"
+"\n"
+" S - Simplex Dumb Phone Control mode. This allows a regular phone user\n"
+" audio-only access to the radio system. In this mode, the\n"
+" transmitter is toggled on and off when the phone user presses the\n"
+" funcchar (*) key on the telephone set. In addition, the transmitter\n"
+" will turn off if the endchar (#) key is pressed. When a user first\n"
+" calls in, the transmitter will be off, and the user can listen for\n"
+" radio traffic. When the user wants to transmit, they press the *\n"
+" key, start talking, then press the * key again or the # key to turn\n"
+" the transmitter off. No other functions can be executed by the\n"
+" user on the phone when this mode is selected. Note: If your\n"
+" radio system is full-duplex, we recommend using either P or D\n"
+" modes as they provide more flexibility.\n"
+"\n"
+" q - Query Status. Sets channel variables and returns + 101 in plan.\n"
+"\n"
+" M - Memory Channel Steer as MXX where XX is the memory channel number.\n"
+"\n"
+" * - Alt Macro to execute (e.g. *7 for status)\n"
"\n";
+;
static int debug = 0; /* Set this >0 for extra debug output */
static int nrpts = 0;
@@ -372,10 +451,17 @@
};
char *discstr = "!!DISCONNECT!!";
+char *newkeystr = "!NEWKEY!";
static char *remote_rig_ft897="ft897";
static char *remote_rig_rbi="rbi";
static char *remote_rig_kenwood="kenwood";
static char *remote_rig_ic706="ic706";
+static char *remote_rig_rtx150="rtx150";
+static char *remote_rig_rtx450="rtx450";
+static char *remote_rig_ppp16="ppp16"; // parallel port programmable 16 channels
+
+#define ISRIG_RTX(x) ((!strcmp(x,remote_rig_rtx150)) || (!strcmp(x,remote_rig_rtx450)))
+#define IS_XPMR(x) (!strncasecmp(x->rxchanname,"rad",3))
#ifdef OLD_ASTERISK
STANDARD_LOCAL_USER;
@@ -396,6 +482,26 @@
#define MAX_SYSSTATES 10
+struct vox {
+ float speech_energy;
+ float noise_energy;
+ int enacount;
+ char voxena;
+ char lastvox;
+ int offdebcnt;
+ int ondebcnt;
+} ;
+
+#define mymax(x,y) ((x > y) ? x : y)
+#define mymin(x,y) ((x < y) ? x : y)
+
+struct rpt_topkey
+{
+char node[TOPKEYMAXSTR];
+int timesince;
+int keyed;
+} ;
+
struct rpt_xlat
{
char funccharseq[MAXXLAT];
@@ -419,9 +525,12 @@
char mode; /* 1 if in tx mode */
char isremote;
char phonemode;
+ char phonevox; /* vox the phone */
char name[MAXNODESTR]; /* identifier (routing) string */
char lasttx;
+ char lasttx1;
char lastrx;
+ char lastrealrx;
char lastrx1;
char connected;
char hasconnected;
@@ -446,8 +555,19 @@
long linklisttimer;
int dtmfed;
int linkunkeytocttimer;
+ struct timeval lastlinktv;
struct ast_frame *lastf1,*lastf2;
struct rpt_chan_stat chan_stat[NRPTSTAT];
+ struct vox vox;
+ char wasvox;
+ int voxtotimer;
+ char voxtostate;
+ char newkey;
+#ifdef OLD_ASTERISK
+ AST_LIST_HEAD(, ast_frame) rxq;
+#else
+ AST_LIST_HEAD_NOLOCK(, ast_frame) rxq;
+#endif
} ;
struct rpt_lstat
@@ -474,6 +594,7 @@
struct rpt_link mylink;
char param[TELEPARAMSIZE];
int submode;
+ unsigned int parrot;
pthread_t threadid;
} ;
@@ -510,17 +631,37 @@
char alternatetail;
};
+/* rpt cmd support */
+#define CMD_DEPTH 1
+#define CMD_STATE_IDLE 0
+#define CMD_STATE_BUSY 1
+#define CMD_STATE_READY 2
+#define CMD_STATE_EXECUTING 3
+
+struct rpt_cmd_struct
+{
+ int state;
+ int functionNumber;
+ char param[MAXDTMF];
+ char digits[MAXDTMF];
+ int command_source;
+};
+
static struct rpt
{
ast_mutex_t lock;
ast_mutex_t remlock;
+ ast_mutex_t statpost_lock;
struct ast_config *cfg;
char reload;
+ char xlink; // cross link state of a share repeater/remote radio
+ unsigned int statpost_seqno;
char *name;
char *rxchanname;
char *txchanname;
- char *remote;
+ char remote;
+ char *remoterig;
struct rpt_chan_stat chan_stat[NRPTSTAT];
unsigned int scram;
@@ -535,6 +676,7 @@
char *link_functions;
char *phone_functions;
char *dphone_functions;
+ char *alt_functions;
char *nodes;
char *extnodes;
char *extnodefile;
@@ -550,6 +692,7 @@
int tailmessagemax;
char *memory;
char *macro;
+ char *tonemacro;
char *startupmacro;
int iobase;
char *ioport;
@@ -575,10 +718,23 @@
int remotetimeoutwarningfreq;
int sysstate_cur;
struct sysstate s[MAX_SYSSTATES];
+ char parrotmode;
+ int parrottime;
+ char *rptnode;
+ char remote_mars;
+ int voxtimeout_ms;
+ int voxrecover_ms;
+ int simplexpatchdelay;
+ int simplexphonedelay;
+ char *statpost_program;
+ char *statpost_url;
} p;
struct rpt_link links;
int unkeytocttimer;
+ time_t lastkeyedtime;
+ time_t lasttxkeyedtime;
char keyed;
+ char txkeyed;
char exttx;
char localtx;
char remoterx;
@@ -592,13 +748,22 @@
char rem_dtmfbuf[MAXDTMF];
char lastdtmfcommand[MAXDTMF];
char cmdnode[50];
- struct ast_channel *rxchannel,*txchannel, *monchannel;
+ char nowchan; // channel now
+ char waschan; // channel selected initially or by command
+ char bargechan; // barge in channel
+ char macropatch; // autopatch via tonemacro state
+ char parrotstate;
+ int parrottimer;
+ unsigned int parrotcnt;
+ struct ast_channel *rxchannel,*txchannel, *monchannel, *parrotchannel;
struct ast_channel *pchannel,*txpchannel, *zaprxchannel, *zaptxchannel;
+ struct ast_channel *voxchannel;
struct ast_frame *lastf1,*lastf2;
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 calldigittimer;
int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer,skedtimer;
int mustid,tailid;
int tailevent;
@@ -631,6 +796,7 @@
int patchdialtime;
int macro_longest;
int phone_longestfunc;
+ int alt_longestfunc;
int dphone_longestfunc;
int link_longestfunc;
int longestfunc;
@@ -643,13 +809,33 @@
char lastnodewhichkeyedusup[MAXNODESTR];
int dtmf_local_timer;
char dtmf_local_str[100];
- struct ast_filestream *monstream;
+ struct ast_filestream *monstream,*parrotstream;
char loginuser[50];
char loginlevel[10];
long authtelltimer;
long authtimer;
int iofd;
time_t start_time,last_activity_time;
+ char lasttone[32];
+ struct rpt_tele *active_telem;
+ struct rpt_topkey topkey[TOPKEYN];
+ int topkeystate;
+ time_t topkeytime;
+ int topkeylong;
+ struct vox vox;
+ char wasvox;
+ int voxtotimer;
+ char voxtostate;
+ int linkposttimer;
+ int keyposttimer;
+ char newkey;
+ char inpadtest;
+#ifdef OLD_ASTERISK
+ AST_LIST_HEAD(, ast_frame) txq;
+#else
+ AST_LIST_HEAD_NOLOCK(, ast_frame) txq;
+#endif
+ char txrealkeyed;
#ifdef __RPT_NOTCH
struct rptfilter
{
@@ -670,6 +856,7 @@
mdc_decoder_t *mdc;
unsigned short lastunit;
#endif
+ struct rpt_cmd_struct cmdAction;
} rpt_vars[MAXRPTS];
struct nodelog {
@@ -685,6 +872,9 @@
static int set_mode_ic706(struct rpt *myrpt, char newmode);
static int simple_command_ft897(struct rpt *myrpt, char command);
static int setrem(struct rpt *myrpt);
+static int setrtx_check(struct rpt *myrpt);
+static int channel_revert(struct rpt *myrpt);
+static int channel_steer(struct rpt *myrpt, char *data);
AST_MUTEX_DEFINE_STATIC(nodeloglock);
@@ -879,12 +1069,95 @@
static int multimode_capable(struct rpt *myrpt)
{
- if(!strcmp(myrpt->remote, remote_rig_ft897))
+ if(!strcmp(myrpt->remoterig, remote_rig_ft897))
return 1;
- if(!strcmp(myrpt->remote, remote_rig_ic706))
+ if(!strcmp(myrpt->remoterig, remote_rig_ic706))
return 1;
return 0;
}
+
+static void voxinit_rpt(struct rpt *myrpt,char enable)
+{
+
+ myrpt->vox.speech_energy = 0.0;
+ myrpt->vox.noise_energy = 0.0;
+ myrpt->vox.enacount = 0;
+ myrpt->vox.voxena = 0;
+ if (!enable) myrpt->vox.voxena = -1;
+ myrpt->vox.lastvox = 0;
+ myrpt->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
+ myrpt->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
+ myrpt->wasvox = 0;
+ myrpt->voxtotimer = 0;
+ myrpt->voxtostate = 0;
+}
+
+static void voxinit_link(struct rpt_link *mylink,char enable)
+{
+
+ mylink->vox.speech_energy = 0.0;
+ mylink->vox.noise_energy = 0.0;
+ mylink->vox.enacount = 0;
+ mylink->vox.voxena = 0;
+ if (!enable) mylink->vox.voxena = -1;
+ mylink->vox.lastvox = 0;
+ mylink->vox.ondebcnt = VOX_ON_DEBOUNCE_COUNT;
+ mylink->vox.offdebcnt = VOX_OFF_DEBOUNCE_COUNT;
+ mylink->wasvox = 0;
+ mylink->voxtotimer = 0;
+ mylink->voxtostate = 0;
+}
+
+static int dovox(struct vox *v,short *buf,int bs)
+{
+
+ int i;
+ float esquare = 0.0;
+ float energy = 0.0;
+ float threshold = 0.0;
+
+ if (v->voxena < 0) return(v->lastvox);
+ for(i = 0; i < bs; i++)
+ {
+ esquare += (float) buf[i] * (float) buf[i];
+ }
+ energy = sqrt(esquare);
+
+ if (energy >= v->speech_energy)
+ v->speech_energy += (energy - v->speech_energy) / 4;
+ else
+ v->speech_energy += (energy - v->speech_energy) / 64;
+
+ if (energy >= v->noise_energy)
+ v->noise_energy += (energy - v->noise_energy) / 64;
+ else
+ v->noise_energy += (energy - v->noise_energy) / 4;
+
+ if (v->voxena) threshold = v->speech_energy / 8;
+ else
+ {
+ threshold = mymax(v->speech_energy / 16,v->noise_energy * 2);
+ threshold = mymin(threshold,VOX_MAX_THRESHOLD);
+ }
+ threshold = mymax(threshold,VOX_MIN_THRESHOLD);
+ if (energy > threshold)
+ {
+ if (v->voxena) v->noise_energy *= 0.75;
+ v->voxena = 1;
+ } else v->voxena = 0;
+ if (v->lastvox != v->voxena)
+ {
+ if (v->enacount++ >= ((v->lastvox) ? v->offdebcnt : v->ondebcnt))
+ {
+ v->lastvox = v->voxena;
+ v->enacount = 0;
+ }
+ } else v->enacount = 0;
+ return(v->lastvox);
+}
+
+
+
/*
* CLI extensions
@@ -896,9 +1169,12 @@
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_nodes(int fd, int argc, char *argv[]);
+static int rpt_do_local_nodes(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 int rpt_do_fun(int fd, int argc, char *argv[]);
+static int rpt_do_fun1(int fd, int argc, char *argv[]);
+static int rpt_do_cmd(int fd, int argc, char *argv[]);
static char debug_usage[] =
"Usage: rpt debug level {0-7}\n"
@@ -920,6 +1196,10 @@
"Usage: rpt nodes <nodename>\n"
" Dumps a list of directly and indirectly connected nodes to the console\n";
+static char usage_local_nodes[] =
+"Usage: rpt localnodes\n"
+" Dumps a list of the locally configured node numbers to the console.\n";
+
static char reload_usage[] =
"Usage: rpt reload\n"
" Reloads app_rpt running config parameters\n";
@@ -932,6 +1212,9 @@
"Usage: rpt fun <nodename> <command>\n"
" Send a DTMF function to a node\n";
+static char cmd_usage[] =
+"Usage: rpt cmd <nodename> <cmd-name> <cmd-index> <cmd-args.\n"
+" Send a command to a node.\n i.e. rpt cmd 2000 ilink 3 2001\n";
static struct ast_cli_entry cli_debug =
{ { "rpt", "debug", "level" }, rpt_do_debug,
@@ -949,6 +1232,10 @@
{ { "rpt", "nodes" }, rpt_do_nodes,
"Dump node list", dump_nodes };
+static struct ast_cli_entry cli_local_nodes =
+ { { "rpt", "localnodes" }, rpt_do_local_nodes,
+ "Dump list of local node numbers", usage_local_nodes };
+
static struct ast_cli_entry cli_lstats =
{ { "rpt", "lstats" }, rpt_do_lstats,
"Dump link statistics", dump_lstats };
@@ -964,6 +1251,14 @@
static struct ast_cli_entry cli_fun =
{ { "rpt", "fun" }, rpt_do_fun,
"Execute a DTMF function", fun_usage };
+
+static struct ast_cli_entry cli_fun1 =
+ { { "rpt", "fun1" }, rpt_do_fun1,
+ "Execute a DTMF function", fun_usage };
+
+static struct ast_cli_entry cli_cmd =
+ { { "rpt", "cmd" }, rpt_do_cmd,
+ "Execute a DTMF function", cmd_usage };
/*
* Telemetry defaults
@@ -1008,6 +1303,7 @@
static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
+static int function_playback(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
/*
* Function table
*/
@@ -1019,7 +1315,8 @@
{"ilink", function_ilink},
{"status", function_status},
{"remote", function_remote},
- {"macro", function_macro}
+ {"macro", function_macro},
+ {"playback", function_playback}
} ;
static long diskavail(struct rpt *myrpt)
@@ -1034,6 +1331,182 @@
return(-1);
}
return(statfsbuf.f_bavail);
+}
+
+static void flush_telem(struct rpt *myrpt)
+{
+ struct rpt_tele *telem;
+ if(debug > 2)
+ ast_log(LOG_NOTICE, "flush_telem()!!");
+ rpt_mutex_lock(&myrpt->lock);
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ if (telem->mode != SETREMOTE) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
+ telem = telem->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
+}
+/*
+ return via error priority
+*/
+static int priority_jump(struct rpt *myrpt, struct ast_channel *chan)
+{
+ int res=0;
+
+ // if (ast_test_flag(&flags,OPT_JUMP) && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
+ if (ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0){
+ res = 0;
+ } else {
+ res = -1;
+ }
+ return res;
+}
+/*
+*/
+static int linkcount(struct rpt *myrpt)
+{
+ struct rpt_link *l;
+ char *reverse_patch_state;
+ int numoflinks;
+
+ reverse_patch_state = "DOWN";
+ numoflinks = 0;
+ l = myrpt->links.next;
+ while(l && (l != &myrpt->links)){
+ if(numoflinks >= MAX_STAT_LINKS){
+ ast_log(LOG_WARNING,
+ "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
+ break;
+ }
+ //if (l->name[0] == '0'){ /* Skip '0' nodes */
+ // reverse_patch_state = "UP";
+ // l = l->next;
+ // continue;
+ //}
+ numoflinks++;
+
+ l = l->next;
+ }
+ ast_log(LOG_NOTICE, "numoflinks=%i\n",numoflinks);
+ return numoflinks;
+}
+/*
+ * Retrieve a memory channel
+ * Return 0 if sucessful,
+ * -1 if channel not found,
+ * 1 if parse error
+ */
+static int retreive_memory(struct rpt *myrpt, char *memory)
+{
+ char tmp[30], *s, *s1, *val;
+
+ if (debug)ast_log(LOG_NOTICE, "memory=%s block=%s\n",memory,myrpt->p.memory);
+
+ val = (char *) ast_variable_retrieve(myrpt->cfg, myrpt->p.memory, memory);
+ if (!val){
+ return -1;
+ }
+ strncpy(tmp,val,sizeof(tmp) - 1);
+ tmp[sizeof(tmp)-1] = 0;
+
+ s = strchr(tmp,',');
+ if (!s)
+ return 1;
+ *s++ = 0;
+ s1 = strchr(s,',');
+ if (!s1)
+ return 1;
+ *s1++ = 0;
+ strncpy(myrpt->freq, tmp, sizeof(myrpt->freq) - 1);
+ strncpy(myrpt->rxpl, s, sizeof(myrpt->rxpl) - 1);
+ strncpy(myrpt->txpl, s, sizeof(myrpt->rxpl) - 1);
+ myrpt->remmode = REM_MODE_FM;
+ myrpt->offset = REM_SIMPLEX;
+ myrpt->powerlevel = REM_MEDPWR;
+ myrpt->txplon = myrpt->rxplon = 0;
+ while(*s1){
+ switch(*s1++){
+ case 'A':
+ case 'a':
+ strcpy(myrpt->rxpl, "100.0");
+ strcpy(myrpt->txpl, "100.0");
+ myrpt->remmode = REM_MODE_AM;
+ break;
+ case 'B':
+ case 'b':
+ strcpy(myrpt->rxpl, "100.0");
+ strcpy(myrpt->txpl, "100.0");
+ myrpt->remmode = REM_MODE_LSB;
+ break;
+ case 'F':
+ myrpt->remmode = REM_MODE_FM;
+ break;
+ case 'L':
+ case 'l':
+ myrpt->powerlevel = REM_LOWPWR;
+ break;
+ case 'H':
+ case 'h':
+ myrpt->powerlevel = REM_HIPWR;
+ break;
+
+ case 'M':
+ case 'm':
+ myrpt->powerlevel = REM_MEDPWR;
+ break;
+
+ case '-':
+ myrpt->offset = REM_MINUS;
+ break;
+
+ case '+':
+ myrpt->offset = REM_PLUS;
+ break;
+
+ case 'S':
+ case 's':
+ myrpt->offset = REM_SIMPLEX;
+ break;
+
+ case 'T':
+ case 't':
+ myrpt->txplon = 1;
+ break;
+
+ case 'R':
+ case 'r':
+ myrpt->rxplon = 1;
+ break;
+
+ case 'U':
+ case 'u':
+ strcpy(myrpt->rxpl, "100.0");
+ strcpy(myrpt->txpl, "100.0");
+ myrpt->remmode = REM_MODE_USB;
+ break;
+ default:
+ return 1;
+ }
+ }
+ return 0;
+}
+/*
+
+*/
+static void birdbath(struct rpt *myrpt)
+{
+ struct rpt_tele *telem;
+ if(debug > 2)
+ ast_log(LOG_NOTICE, "birdbath!!");
+ rpt_mutex_lock(&myrpt->lock);
+ telem = myrpt->tele.next;
+ while(telem != &myrpt->tele)
+ {
+ if (telem->mode == PARROT) ast_softhangup(telem->chan,AST_SOFTHANGUP_DEV);
+ telem = telem->next;
+ }
+ rpt_mutex_unlock(&myrpt->lock);
}
static void do_dtmf_phone(struct rpt *myrpt, struct rpt_link *mylink, char c)
@@ -1068,7 +1541,7 @@
char datestr[100];
if (!myrpt->p.archivedir) return;
- nodep = (struct nodelog *)malloc(sizeof(struct nodelog));
+ nodep = (struct nodelog *)ast_malloc(sizeof(struct nodelog));
if (nodep == NULL)
{
ast_log(LOG_ERROR,"Cannot get memory for node log");
@@ -1153,7 +1626,33 @@
}
}
-static int openserial(char *fname)
+static int setdtr(int fd, int enable)
+{
+struct termios mode;
+
+ if (fd < 0) return -1;
+ if (tcgetattr(fd, &mode)) {
+ ast_log(LOG_WARNING, "Unable to get serial parameters for dtr: %s\n", strerror(errno));
+ return -1;
+ }
+ if (enable)
+ {
+ cfsetspeed(&mode, B9600);
+ }
+ else
+ {
+ cfsetspeed(&mode, B0);
+ usleep(100000);
+ }
+ if (tcsetattr(fd, TCSADRAIN, &mode)) {
+ ast_log(LOG_WARNING, "Unable to set serial parameters for dtr: %s\n", strerror(errno));
+ return -1;
+ }
+ if (enable) usleep(100000);
+ return 0;
+}
+
+static int openserial(struct rpt *myrpt,char *fname)
{
struct termios mode;
int fd;
@@ -1169,23 +1668,25 @@
ast_log(LOG_WARNING, "Unable to get serial parameters on %s: %s\n", fname, strerror(errno));
return -1;
}
-#ifndef SOLARIS
+#ifndef SOLARIS
cfmakeraw(&mode);
#else
mode.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
- mode.c_oflag &= ~OPOST;
mode.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
mode.c_cflag &= ~(CSIZE|PARENB|CRTSCTS);
mode.c_cflag |= CS8;
- mode.c_cc[TIME] = 3;
- mode.c_cc[MAX] = 1;
+ mode.c_cc[VTIME] = 3;
+ mode.c_cc[VMIN] = 1;
#endif
cfsetispeed(&mode, B9600);
cfsetospeed(&mode, B9600);
if (tcsetattr(fd, TCSANOW, &mode))
ast_log(LOG_WARNING, "Unable to set serial parameters on %s: %s\n", fname, strerror(errno));
+ if(!strcmp(myrpt->remoterig, remote_rig_kenwood)) setdtr(fd,0);
+ usleep(100000);
+ if (debug)ast_log(LOG_NOTICE,"Opened serial port %s\n",fname);
return(fd);
}
@@ -1343,7 +1844,24 @@
return(i);
}
-
+/*
+ send asterisk frame text message on the current tx channel
+*/
+static int send_usb_txt(struct rpt *myrpt, char *txt)
+{
+ struct ast_frame wf;
+
+ if (debug)ast_log(LOG_NOTICE, "send_usb_txt %s\n",txt);
+ wf.frametype = AST_FRAME_TEXT;
+ wf.subclass = 0;
+ wf.offset = 0;
+ wf.mallocd = 0;
+ wf.datalen = strlen(txt) + 1;
+ wf.data = txt;
+ wf.samples = 0;
+ ast_write(myrpt->txchannel,&wf);
+ return 0;
+}
/* must be called locked */
static void __mklinklist(struct rpt *myrpt, struct rpt_link *mylink, char *buf)
{
@@ -1352,6 +1870,7 @@
int i,spos;
buf[0] = 0; /* clear output buffer */
+ if (myrpt->remote) return;
/* go thru all links */
for(l = myrpt->links.next; l != &myrpt->links; l = l->next)
{
@@ -1404,6 +1923,42 @@
if (l->name[0] == '0') continue;
l->linklisttimer = LINKLISTSHORTTIME;
}
+ myrpt->linkposttimer = LINKPOSTSHORTTIME;
+ return;
+}
+
+static void statpost(struct rpt *myrpt,char *pairs)
+{
+char *str,*astr;
+char *astrs[100];
+int n,pid;
+time_t now;
+unsigned int seq;
+
+ if (!myrpt->p.statpost_url) return;
+ str = ast_malloc(strlen(pairs) + strlen(myrpt->p.statpost_url) + 200);
+ astr = ast_strdup(myrpt->p.statpost_program);
+ if ((!str) || (!astr)) return;
+ n = finddelim(astr,astrs,100);
+ if (n < 1) return;
+ ast_mutex_lock(&myrpt->statpost_lock);
+ seq = ++myrpt->statpost_seqno;
+ ast_mutex_unlock(&myrpt->statpost_lock);
+ astrs[n++] = str;
+ astrs[n] = NULL;
+ time(&now);
+ sprintf(str,"%s?node=%s&time=%u&seqno=%u",myrpt->p.statpost_url,
+ myrpt->name,(unsigned int) now,seq);
+ if (pairs) sprintf(str + strlen(str),"&%s",pairs);
+ if (!(pid = fork()))
+ {
+ execv(astrs[0],astrs);
+ ast_log(LOG_ERROR, "exec of %s failed.\n", astrs[0]);
+ perror("asterisk");
+ exit(0);
+ }
+ ast_free(astr);
+ ast_free(str);
return;
}
@@ -1490,7 +2045,7 @@
return i + 1;
}
}
- param = NULL;
+ *param = NULL;
return 0;
}
@@ -1536,6 +2091,14 @@
if ((**x < '0') || (**x > '9')) xoff = 1; else xoff = 0;
if ((**y < '0') || (**y > '9')) yoff = 1; else yoff = 0;
return(strcmp((*x) + xoff,(*y) + yoff));
+}
+
+static int topcompar(const void *a, const void *b)
+{
+struct rpt_topkey *x = (struct rpt_topkey *) a;
+struct rpt_topkey *y = (struct rpt_topkey *) b;
+
+ return(x->timesince - y->timesince);
}
#ifdef __RPT_NOTCH
@@ -1646,8 +2209,12 @@
memset(&rpt_vars[n].p,0,sizeof(rpt_vars[n].p));
if (init)
{
- /* clear all the fields in the structure after 'p' */
- memset(&rpt_vars[n].p + sizeof(rpt_vars[0].p), 0, sizeof(rpt_vars[0]) - sizeof(rpt_vars[0].p) - offsetof(typeof(rpt_vars[0]), p));
+ 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;
@@ -1675,6 +2242,23 @@
val = (char *) ast_variable_retrieve(cfg,this,"totime");
if (val) rpt_vars[n].p.totime = atoi(val);
else rpt_vars[n].p.totime = TOTIME;
+ val = (char *) ast_variable_retrieve(cfg,this,"voxtimeout");
+ if (val) rpt_vars[n].p.voxtimeout_ms = atoi(val);
+ else rpt_vars[n].p.voxtimeout_ms = VOX_TIMEOUT_MS;
+ val = (char *) ast_variable_retrieve(cfg,this,"voxrecover");
+ if (val) rpt_vars[n].p.voxrecover_ms = atoi(val);
+ else rpt_vars[n].p.voxrecover_ms = VOX_RECOVER_MS;
+ val = (char *) ast_variable_retrieve(cfg,this,"simplexpatchdelay");
+ if (val) rpt_vars[n].p.simplexpatchdelay = atoi(val);
+ else rpt_vars[n].p.simplexpatchdelay = SIMPLEX_PATCH_DELAY;
+ val = (char *) ast_variable_retrieve(cfg,this,"simplexphonedelay");
+ if (val) rpt_vars[n].p.simplexphonedelay = atoi(val);
+ else rpt_vars[n].p.simplexphonedelay = SIMPLEX_PHONE_DELAY;
+ val = (char *) ast_variable_retrieve(cfg,this,"statpost_program");
+ if (val) rpt_vars[n].p.statpost_program = val;
+ else rpt_vars[n].p.statpost_program = STATPOST_PROGRAM;
+ rpt_vars[n].p.statpost_url =
+ (char *) ast_variable_retrieve(cfg,this,"statpost_url");
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);
@@ -1692,6 +2276,9 @@
val = (char *) ast_variable_retrieve(cfg,this,"macro");
if (!val) val = MACRO;
rpt_vars[n].p.macro = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"tonemacro");
+ if (!val) val = TONEMACRO;
+ rpt_vars[n].p.tonemacro = val;
val = (char *) ast_variable_retrieve(cfg,this,"startup_macro");
if (val) rpt_vars[n].p.startupmacro = val;
val = (char *) ast_variable_retrieve(cfg,this,"iobase");
@@ -1699,7 +2286,7 @@
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;
+ rpt_vars[n].p.iobase = DEFAULT_IOBASE;
val = (char *) ast_variable_retrieve(cfg,this,"ioport");
rpt_vars[n].p.ioport = val;
val = (char *) ast_variable_retrieve(cfg,this,"functions");
@@ -1717,6 +2304,8 @@
if (val) rpt_vars[n].p.phone_functions = val;
val = (char *) ast_variable_retrieve(cfg,this,"dphone_functions");
if (val) rpt_vars[n].p.dphone_functions = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"alt_functions");
+ if (val) rpt_vars[n].p.alt_functions = val;
val = (char *) ast_variable_retrieve(cfg,this,"funcchar");
if (!val) rpt_vars[n].p.funcchar = FUNCCHAR; else
rpt_vars[n].p.funcchar = *val;
@@ -1747,6 +2336,17 @@
val = (char *) ast_variable_retrieve(cfg,this,"authlevel");
if (val) rpt_vars[n].p.authlevel = atoi(val);
else rpt_vars[n].p.authlevel = 0;
+ val = (char *) ast_variable_retrieve(cfg,this,"parrot");
+ if (val) rpt_vars[n].p.parrotmode = ast_true(val) * 2;
+ else rpt_vars[n].p.parrotmode = 0;
+ val = (char *) ast_variable_retrieve(cfg,this,"parrottime");
+ if (val) rpt_vars[n].p.parrottime = atoi(val);
+ else rpt_vars[n].p.parrottime = PARROTTIME;
+ val = (char *) ast_variable_retrieve(cfg,this,"rptnode");
+ rpt_vars[n].p.rptnode = val;
+ val = (char *) ast_variable_retrieve(cfg,this,"mars");
+ if (val) rpt_vars[n].p.remote_mars = atoi(val);
+ else rpt_vars[n].p.remote_mars = 0;
val = (char *) ast_variable_retrieve(cfg,this,"monminblocks");
if (val) rpt_vars[n].p.monminblocks = atol(val);
else rpt_vars[n].p.monminblocks = DEFAULT_MONITOR_MIN_DISK_BLOCKS;
@@ -1865,6 +2465,17 @@
j = strlen(vp->name);
if (j > rpt_vars[n].dphone_longestfunc)
rpt_vars[n].dphone_longestfunc = j;
+ vp = vp->next;
+ }
+ }
+ rpt_vars[n].alt_longestfunc = 0;
+ if (rpt_vars[n].p.alt_functions)
+ {
+ vp = ast_variable_browse(cfg, rpt_vars[n].p.alt_functions);
+ while(vp){
+ j = strlen(vp->name);
+ if (j > rpt_vars[n].alt_longestfunc)
+ rpt_vars[n].alt_longestfunc = j;
vp = vp->next;
}
}
@@ -2012,14 +2623,16 @@
static int rpt_do_stats(int fd, int argc, char *argv[])
{
- int i,j;
+ int i,j,numoflinks;
int dailytxtime, dailykerchunks;
+ time_t now;
int totalkerchunks, dailykeyups, totalkeyups, timeouts;
int totalexecdcommands, dailyexecdcommands, hours, minutes, seconds;
+ int uptime;
long long totaltxtime;
struct rpt_link *l;
char *listoflinks[MAX_STAT_LINKS];
- char *lastnodewhichkeyedusup, *lastdtmfcommand;
+ char *lastdtmfcommand,*parrot_ena;
char *tot_state, *ider_state, *patch_state;
char *reverse_patch_state, *sys_ena, *tot_ena, *link_ena, *patch_ena;
char *sch_ena, *input_signal, *called_number, *user_funs, *tail_type;
@@ -2030,21 +2643,19 @@
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;
-
+ input_signal = not_applicable;
+ called_number = lastdtmfcommand = NULL;
+
+ time(&now);
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 */
-
+ uptime = (int)(now - starttime);
dailytxtime = myrpt->dailytxtime;
totaltxtime = myrpt->totaltxtime;
dailykeyups = myrpt->dailykeyups;
@@ -2057,28 +2668,38 @@
/* Traverse the list of connected nodes */
reverse_patch_state = "DOWN";
- j = 0;
+ numoflinks = 0;
l = myrpt->links.next;
while(l && (l != &myrpt->links)){
+ if(numoflinks >= MAX_STAT_LINKS){
+ ast_log(LOG_NOTICE,
+ "maximum number of links exceeds %d in rpt_do_stats()!",MAX_STAT_LINKS);
+ break;
+ }
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++;
+ listoflinks[numoflinks] = ast_strdup(l->name);
+ if(listoflinks[numoflinks] == NULL){
+ break;
+ }
+ else{
+ numoflinks++;
+ }
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->p.parrotmode)
+ parrot_ena = "ENABLED";
+ else
+ parrot_ena = "DISABLED";
if(myrpt->p.s[myrpt->p.sysstate_cur].txdisable)
sys_ena = "DISABLED";
@@ -2149,23 +2770,19 @@
}
if(strlen(myrpt->exten)){
- called_number = ast_strdupa(myrpt->exten);
- if(!called_number)
- called_number = not_applicable;
+ called_number = ast_strdup(myrpt->exten);
}
if(strlen(myrpt->lastdtmfcommand)){
- lastdtmfcommand = ast_strdupa(myrpt->lastdtmfcommand);
- if(!lastdtmfcommand)
- lastdtmfcommand = not_applicable;
- }
-
+ lastdtmfcommand = ast_strdup(myrpt->lastdtmfcommand);
+ }
rpt_mutex_unlock(&myrpt->lock); /* UNLOCK */
ast_cli(fd, "************************ NODE %s STATISTICS *************************\n\n", myrpt->name);
ast_cli(fd, "Selected system state............................: %d\n", myrpt->p.sysstate_cur);
ast_cli(fd, "Signal on input..................................: %s\n", input_signal);
ast_cli(fd, "System...........................................: %s\n", sys_ena);
+ ast_cli(fd, "Parrot Mode......................................: %s\n", parrot_ena);
ast_cli(fd, "Scheduler........................................: %s\n", sch_ena);
ast_cli(fd, "Tail Time........................................: %s\n", tail_type);
ast_cli(fd, "Time out timer...................................: %s\n", tot_ena);
@@ -2178,7 +2795,8 @@
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);
+ ast_cli(fd, "Last DTMF command executed.......................: %s\n",
+ (lastdtmfcommand && strlen(lastdtmfcommand)) ? lastdtmfcommand : not_applicable);
hours = dailytxtime/3600000;
dailytxtime %= 3600000;
minutes = dailytxtime/60000;
@@ -2186,7 +2804,7 @@
seconds = dailytxtime/1000;
dailytxtime %= 1000;
- ast_cli(fd, "TX time today ...................................: %02d:%02d:%02d.%d\n",
+ ast_cli(fd, "TX time today....................................: %02d:%02d:%02d.%d\n",
hours, minutes, seconds, dailytxtime);
hours = (int) totaltxtime/3600000;
@@ -2198,33 +2816,51 @@
ast_cli(fd, "TX time since system initialization..............: %02d:%02d:%02d.%d\n",
hours, minutes, seconds, (int) totaltxtime);
+
+ hours = uptime/3600;
+ uptime %= 3600;
+ minutes = uptime/60;
+ uptime %= 60;
+
+ ast_cli(fd, "Uptime...........................................: %02d:%02d:%02d\n",
+ hours, minutes, uptime);
+
ast_cli(fd, "Nodes currently connected to us..................: ");
- for(j = 0 ;; j++){
- if(!listoflinks[j]){
- if(!j){
- ast_cli(fd,"<NONE>");
+ if(!numoflinks){
+ ast_cli(fd,"<NONE>");
+ }
+ else{
+ for(j = 0 ;j < numoflinks; j++){
+ ast_cli(fd, "%s", listoflinks[j]);
+ if(j % 4 == 3){
+ ast_cli(fd, "\n");
+ ast_cli(fd, " : ");
+ }
+ else{
+ if((numoflinks - 1) - j > 0)
+ ast_cli(fd, ", ");
}
- 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........................................: %s\n", patch_ena);
ast_cli(fd, "Autopatch state..................................: %s\n", patch_state);
- ast_cli(fd, "Autopatch called number..........................: %s\n", called_number);
+ ast_cli(fd, "Autopatch called number..........................: %s\n",
+ (called_number && strlen(called_number)) ? called_number : not_applicable);
ast_cli(fd, "Reverse patch/IAXRPT connected...................: %s\n", reverse_patch_state);
ast_cli(fd, "User linking commands............................: %s\n", link_ena);
ast_cli(fd, "User functions...................................: %s\n\n", user_funs);
+
+ for(j = 0; j < numoflinks; j++){ /* ast_free() all link names */
+ ast_free(listoflinks[j]);
+ }
+ if(called_number){
+ ast_free(called_number);
+ }
+ if(lastdtmfcommand){
+ ast_free(lastdtmfcommand);
+ }
return RESULT_SUCCESS;
}
}
@@ -2264,7 +2900,7 @@
l = l->next;
continue;
}
- if((s = (struct rpt_lstat *) malloc(sizeof(struct rpt_lstat))) == NULL){
[... 5114 lines stripped ...]
More information about the asterisk-commits
mailing list