Skip to content
Snippets Groups Projects
app_rpt.c 390 KiB
Newer Older
  • Learn to ignore specific revisions
  • #define	NEW_ASTERISK
    /* #define OLD_ASTERISK */
    
    /*
     * Asterisk -- An open source telephony toolkit.
    
     * Copyright (C) 2002-2008, Jim Dixon, WB6NIL
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Jim Dixon, WB6NIL <jim@lambdatel.com>
    
     * Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * See http://www.asterisk.org for more information about
     * the Asterisk project. Please do not directly contact
     * any of the maintainers of this project for assistance;
     * the project provides a web site, mailing lists and IRC
     * channels for your use.
     *
    
    Mark Spencer's avatar
    Mark Spencer committed
     * This program is free software, distributed under the terms of
    
     * the GNU General Public License Version 2. See the LICENSE file
     * at the top of the source tree.
     */
    
     * \brief Radio Repeater / Remote Base program 
    
     *  version 0.115 5/12/08 2055 EDT
    
     * \author Jim Dixon, WB6NIL <jim@lambdatel.com>
     *
     * \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar@rodgers.sdcoxmail.com>
    
     * \note Steven Henke, W9SH, <w9sh@arrl.net> added a few features here and there.
     *
    
     * See http://www.zapatatelephony.org/app_rpt.html
     *
    
    Mark Spencer's avatar
    Mark Spencer committed
     *
    
     * Repeater / Remote Functions:
     * "Simple" Mode:  * - autopatch access, # - autopatch hangup
     * Normal mode:
    
     * 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.
    
     *  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:
     *
     *  1 - System warm boot
     *  2 - System enable
     *  3 - System disable
    
     *  4 - Test Tone On/Off
    
     *  5 - Dump System Variables on Console (debug)
     *  6 - PTT (phone mode only)
    
     *  7 - Time out timer enable
     *  8 - Time out timer disable
     *  9 - Autopatch enable
     *  10 - Autopatch disable
     *  11 - Link enable
     *  12 - Link disable
     *  13 - Query System State
     *  14 - Change System State
     *  15 - Scheduler Enable
     *  16 - Scheduler Disable
     *  17 - User functions (time, id, etc) enable
     *  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:
     *
     *  1 - Disconnect specified link
     *  2 - Connect specified link -- monitor only
     *  3 - Connect specified link -- tranceive
     *  4 - Enter command mode on specified link
     *  5 - System status
     *  6 - Disconnect all links
    
     *  11 - Disconnect a previously permanently connected link
     *  12 - Permanently connect specified link -- monitor only
     *  13 - Permanently connect specified link -- tranceive
     *  15 - Full system status (all nodes)
     *  16 - Reconnect links disconnected with "disconnect all links"
     *  200 thru 215 - (Send DTMF 0-9,*,#,A-D) (200=0, 201=1, 210=*, etc)
    
     *  1 - Recall Memory MM  (*000-*099) (Gets memory from rpt.conf)
     *  2 - Set VFO MMMMM*KKK*O   (Mhz digits, Khz digits, Offset)
     *  3 - Set Rx PL Tone HHH*D*
     *  4 - Set Tx PL Tone HHH*D* (Not currently implemented with DHE RBI-1)
     *  5 - Link Status (long)
     *  6 - Set operating mode M (FM, USB, LSB, AM, etc)
    
     *  100 - RX PL off (Default)
     *  101 - RX PL On
     *  102 - TX PL Off (Default)
     *  103 - TX PL On
     *  104 - Low Power
     *  105 - Med Power
     *  106 - Hi Power
    
     *  107 - Bump Down 20 Hz
     *  108 - Bump Down 100 Hz
     *  109 - Bump Down 500 Hz
     *  110 - Bump Up 20 Hz
     *  111 - Bump Up 100 Hz
     *  112 - Bump Up 500 Hz
     *  113 - Scan Down Slow
     *  114 - Scan Down Medium
     *  115 - Scan Down Fast
     *  116 - Scan Up Slow
     *  117 - Scan Up Medium
     *  118 - Scan Up Fast
     *  119 - Transmit allowing auto-tune
     *  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)
     *
     * 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
     *
    
    /* Un-comment the following to include support for MDC-1200 digital tone
       signalling protocol (using KA6SQG's GPL'ed implementation) */
    /* #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) */
    /* #include "rpt_notch.c" */
    
    /* 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	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	KENWOOD_RETRIES 5
    #define	TOPKEYN 32
    #define	TOPKEYWAIT 3
    #define	TOPKEYMAXSTR 30
    
    #define	AUTHTELLTIME 7000
    #define	AUTHTXTIME 1000
    #define	AUTHLOGOUTTIME 25000
    
    #define	DISC_TIME 10000  /* report disc after 10 seconds of no connect */
    #define	MAX_RETRIES 5
    
    #define	MAX_RETRIES_PERM 1000000000
    
    Jim Dixon's avatar
    Jim Dixon committed
    #define	REDUNDANT_TX_TIME 2000
    
    
    #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	MONITOR_DISK_BLOCKS_PER_MINUTE 38
    
    #define	DEFAULT_MONITOR_MIN_DISK_BLOCKS 10000
    #define	DEFAULT_REMOTE_INACT_TIMEOUT (15 * 60)
    #define	DEFAULT_REMOTE_TIMEOUT (60 * 60)
    #define	DEFAULT_REMOTE_TIMEOUT_WARNING (3 * 60)
    #define	DEFAULT_REMOTE_TIMEOUT_WARNING_FREQ 30
    
    
    #define	EXTNODES "extnodes"
    
    #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_CIV_ADDR 0x58
    
    
    #define	MAXCONNECTTIME 5000
    
    #define MAXNODESTR 300
    
    
    #define MAXNODELEN 16
    
    #define MAXIDENTLEN 32
    
    
    #define	DTMF_LOCAL_TIME 250
    #define	DTMF_LOCAL_STARTTIME 500
    
    #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, 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, TOPKEY,
    	TIMEOUT_WARNING, ACT_TIMEOUT_WARNING, LINKUNKEY, UNAUTHTX, PARROT,
    	STATS_TIME_LOCAL};
    
    
    enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
    
    enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
    
    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, 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};
    
    enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,
          HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST};
    
    #include "asterisk.h"
    
    ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    #include <signal.h>
    
    #include <stdint.h>
    
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    
    #include <sys/types.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <sys/stat.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <dirent.h>
    #include <ctype.h>
    
    #include <sys/stat.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <sys/time.h>
    #include <sys/file.h>
    #include <sys/ioctl.h>
    
    #ifdef HAVE_SYS_IO_H
    
    #include <sys/vfs.h>
    
    Mark Spencer's avatar
    Mark Spencer committed
    #include <math.h>
    
    #include <dahdi/user.h>
    #include <dahdi/tonezone.h>
    
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #include "asterisk/utils.h"
    #include "asterisk/lock.h"
    #include "asterisk/file.h"
    
    #include "asterisk/logger.h"
    
    #include "asterisk/channel.h"
    #include "asterisk/callerid.h"
    #include "asterisk/pbx.h"
    #include "asterisk/module.h"
    #include "asterisk/translate.h"
    
    #include "asterisk/options.h"
    
    #include "asterisk/cli.h"
    #include "asterisk/config.h"
    #include "asterisk/say.h"
    #include "asterisk/localtime.h"
    
    #include "asterisk/cdr.h"
    #include "asterisk/options.h"
    #include "asterisk/manager.h"
    
    #include "asterisk/app.h"
    
    
    #include <termios.h>
    
    #ifdef	NEW_ASTERISK
    struct ast_flags config_flags = { CONFIG_FLAG_WITHCOMMENTS };
    #endif
    
    
    /* Start a tone-list going */
    int ast_playtones_start(struct ast_channel *chan, int vol, const char* tonelist, int interruptible);
    /*! Stop the tones from playing */
    void ast_playtones_stop(struct ast_channel *chan);
    
    static  char *tdesc = "Radio Repeater / Remote Base  version 0.115  5/12/2008";
    
    static char *app = "Rpt";
    
    static char *synopsis = "Radio Repeater/Remote Base Control System";
    
    static char *descrip = 
    
    "  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"
    "\n"
    "    Options are as follows:\n"
    "\n"
    "        X - Normal endpoint mode WITHOUT security check. Only specify\n"
    "            this if you have checked security already (like with an IAX2\n"
    "            user/password or something).\n"
    "\n"
    
    "        Rannounce-string[|timeout[|timeout-destination]] - Amateur Radio\n"
    
    "            Reverse Autopatch. Caller is put on hold, and announcement (as\n"
    "            specified by the 'announce-string') is played on radio system.\n"
    "            Users of radio system can access autopatch, dial specified\n"
    "            code, and pick up call. Announce-string is list of names of\n"
    "            recordings, or \"PARKED\" to substitute code for un-parking,\n"
    "            or \"NODE\" to substitute node number.\n"
    "\n"
    "        P - Phone Control mode. This allows a regular phone user to have\n"
    "            full control and audio access to the radio system. For the\n"
    "            user to have DTMF control, the 'phone_functions' parameter\n"
    "            must be specified for the node in 'rpt.conf'. An additional\n"
    "            function (cop,6) must be listed so that PTT control is available.\n"
    "\n"
    "        D - Dumb Phone Control mode. This allows a regular phone user to\n"
    "            have full control and audio access to the radio system. In this\n"
    "            mode, the PTT is activated for the entire length of the call.\n"
    "            For the user to have DTMF control (not generally recomended in\n"
    "            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"
    
    static int debug = 0;  /* Set this >0 for extra debug output */
    
    static const char remdtmfstr[] = "0123456789*#ABCD";
    
    
    enum {TOP_TOP,TOP_WON,WON_BEFREAD,BEFREAD_AFTERREAD};
    
    int max_chan_stat [] = {22000,1000,22000,100,22000,2000,22000};
    
    #define NRPTSTAT 7
    
    struct rpt_chan_stat
    {
    	struct timeval last;
    	long long total;
    	unsigned long count;
    	unsigned long largest;
    	struct timeval largest_time;
    };
    
    
    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_tm271="tm271";
    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;
    LOCAL_USER_DECL;
    #endif
    
    Mark Spencer's avatar
    Mark Spencer committed
    #define	MSWAIT 200
    #define	HANGTIME 5000
    #define	TOTIME 180000
    #define	IDTIME 300000
    #define	MAXRPTS 20
    
    #define	MAXXLAT 20
    #define	MAXXLATTIME 3
    
    #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];
    char	endcharseq[MAXXLAT];
    char	passchars[MAXXLAT];
    int	funcindex;
    int	endindex;
    time_t	lastone;
    } ;
    
    static time_t	starttime = 0;
    
    static  pthread_t rpt_master_thread;
    
    struct rpt;
    
    struct rpt_link
    {
    	struct rpt_link *next;
    	struct rpt_link *prev;
    	char	mode;			/* 1 if in tx mode */
    	char	isremote;
    
    	char	phonevox;		/* vox the phone */
    
    	char	name[MAXNODESTR];	/* identifier (routing) string */
    	char	lasttx;
    
    	char	lastrealrx;
    	char	lastrx1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    	char	hasconnected;
    
    	char	perma;
    	char	thisconnected;
    
    	char	disced;
    
    Jim Dixon's avatar
    Jim Dixon committed
    	char	killme;
    
    	long	elaptime;
    	long	disctime;
    	long 	retrytimer;
    
    Jim Dixon's avatar
    Jim Dixon committed
    	long	retxtimer;
    
    	int	retries;
    
    	struct ast_channel *chan;	
    	struct ast_channel *pchan;	
    
    	char	linklist[MAXLINKLIST];
    	time_t	linklistreceived;
    	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
    {
    	struct	rpt_lstat *next;
    	struct	rpt_lstat *prev;
    	char	peer[MAXPEERSTR];
    	char	name[MAXNODESTR];
    	char	mode;
    	char	outbound;
    	char	reconnects;
    
    	char	thisconnected;
    
    	struct	rpt_chan_stat chan_stat[NRPTSTAT];
    
    struct rpt_tele
    {
    	struct rpt_tele *next;
    	struct rpt_tele *prev;
    	struct rpt *rpt;
    
    	intptr_t submode;
    
    Steve Murphy's avatar
    Steve Murphy committed
    	uintptr_t  parrot;
    
    struct function_table_tag
    {
    	char action[ACTIONSIZE];
    
    	int (*function)(struct rpt *myrpt, char *param, char *digitbuf, 
    		int command_source, struct rpt_link *mylink);
    
    } ;
    
    /* Used to store the morse code patterns */
    
    struct morse_bits
    {		  
    	int len;
    	int ddcomb;
    } ;
    
    struct telem_defaults
    {
    	char name[20];
    	char value[80];
    } ;
    
    
    
    struct sysstate
    {
    	char txdisable;
    	char totdisable;
    	char linkfundisable;
    	char autopatchdisable;
    	char schedulerdisable;
    	char userfundisable;
    	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;
    };
    
    
    Mark Spencer's avatar
    Mark Spencer committed
    static struct rpt
    {
    
    	ast_mutex_t remlock;
    	ast_mutex_t statpost_lock;
    
    	char xlink;		 							// cross link state of a share repeater/remote radio
    	unsigned int statpost_seqno;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char *rxchanname;
    	char *txchanname;
    
    	char remote;
    	char *remoterig;
    	struct	rpt_chan_stat chan_stat[NRPTSTAT];
    	unsigned int scram;
    
    		char *ourcontext;
    		char *ourcallerid;
    		char *acctcode;
    		char *ident;
    		char *tonezone;
    
    		char *functions;
    		char *link_functions;
    		char *phone_functions;
    		char *dphone_functions;
    		char *alt_functions;
    		char *nodes;
    		char *extnodes;
    		char *extnodefile;
    
    		int totime;
    		int idtime;
    		int tailmessagetime;
    		int tailsquashedtime;
    		int duplex;
    		int politeid;
    
    		char *tailmessages[500];
    		int tailmessagemax;
    		char	*memory;
    		char	*macro;
    		char	*tonemacro;
    		char	*startupmacro;
    
    		char notelemtx;
    		char propagate_dtmf;
    		char propagate_phonedtmf;
    		char linktolink;
    		unsigned char civaddr;
    		struct rpt_xlat inxlat;
    		struct rpt_xlat outxlat;
    		char *archivedir;
    		int authlevel;
    		char *csstanzaname;
    		char *skedstanzaname;
    		char *txlimitsstanzaname;
    		long monminblocks;
    		int remoteinacttimeout;
    		int remotetimeout;
    		int remotetimeoutwarning;
    		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;
    
    	time_t lastkeyedtime;
    	time_t lasttxkeyedtime;
    
    	char tounkeyed;
    	char tonotify;
    
    	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, *dahdirxchannel, *dahditxchannel;
    
    	struct ast_channel *voxchannel;
    	struct ast_frame *lastf1,*lastf2;
    
    	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 dtmfidx,rem_dtmfidx;
    	int dailytxtime,dailykerchunks,totalkerchunks,dailykeyups,totalkeyups,timeouts;
    
    	int totalexecdcommands, dailyexecdcommands;
    
    	long	retxtimer;
    	long	rerxtimer;
    
    Mark Spencer's avatar
    Mark Spencer committed
    	char exten[AST_MAX_EXTENSION];
    
    	char freq[MAXREMSTR],rxpl[MAXREMSTR],txpl[MAXREMSTR];
    
    	char offset;
    	char powerlevel;
    	char txplon;
    	char rxplon;
    
    	char remmode;
    	char tunerequest;
    	char hfscanmode;
    	int hfscanstatus;
    
    	char savednodes[MAXNODESTR];
    	int stopgen;
    
    	char patchfarenddisconnect;
    	char patchnoct;
    	char patchquiet;
    	char patchcontext[MAXPATCHCONTEXT];
    	int patchdialtime;
    
    	int alt_longestfunc;
    
    	int link_longestfunc;
    	int longestfunc;
    
    	int longestnode;
    	int threadrestarts;		
    
    	time_t disgorgetime;
    	time_t lastthreadrestarttime;
    
    	long	macrotimer;
    	char	lastnodewhichkeyedusup[MAXNODESTR];
    	int	dtmf_local_timer;
    	char	dtmf_local_str[100];
    	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;
    
    		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
    
    	struct rpt_cmd_struct cmdAction;
    
    struct nodelog {
    struct nodelog *next;
    struct nodelog *prev;
    time_t	timestamp;
    char archivedir[MAXNODESTR];
    char str[MAXNODESTR * 2];
    } nodelog;
    
    static int service_scan(struct rpt *myrpt);
    static int set_mode_ft897(struct rpt *myrpt, char newmode);
    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);
    
    AST_MUTEX_DEFINE_STATIC(nodelookuplock);
    
    
    #ifdef	APP_RPT_LOCK_DEBUG
    
    #warning COMPILING WITH LOCK-DEBUGGING ENABLED!!
    
    #define	MAXLOCKTHREAD 100
    
    
    #define rpt_mutex_lock(x) _rpt_mutex_lock(x,myrpt,__LINE__)
    #define rpt_mutex_unlock(x) _rpt_mutex_unlock(x,myrpt,__LINE__)
    
    
    struct lockthread
    {
    	pthread_t id;
    	int lockcount;
    	int lastlock;
    	int lastunlock;
    } lockthreads[MAXLOCKTHREAD];
    
    
    struct by_lightning
    {
    	int line;
    	struct timeval tv;
    	struct rpt *rpt;
    	struct lockthread lockthread;
    } lock_ring[32];
    
    int lock_ring_index = 0;
    
    AST_MUTEX_DEFINE_STATIC(locklock);
    
    static struct lockthread *get_lockthread(pthread_t id)
    {
    
    	for(i = 0; i < MAXLOCKTHREAD; i++)
    	{
    		if (lockthreads[i].id == id) return(&lockthreads[i]);
    
    }
    
    static struct lockthread *put_lockthread(pthread_t id)
    {
    
    	for(i = 0; i < MAXLOCKTHREAD; i++)
    	{
    
    		if (lockthreads[i].id == id)
    			return(&lockthreads[i]);
    	}
    
    	for(i = 0; i < MAXLOCKTHREAD; i++)
    	{
    		if (!lockthreads[i].id)
    		{
    
    			lockthreads[i].lockcount = 0;
    			lockthreads[i].lastlock = 0;
    			lockthreads[i].lastunlock = 0;
    			lockthreads[i].id = id;
    
    			return(&lockthreads[i]);
    
    }
    
    
    static void rpt_mutex_spew(void)
    {
    	struct by_lightning lock_ring_copy[32];
    	int lock_ring_index_copy;
    
    	struct timeval lasttv;
    
    	ast_mutex_lock(&locklock);
    	memcpy(&lock_ring_copy, &lock_ring, sizeof(lock_ring_copy));
    	lock_ring_index_copy = lock_ring_index;
    	ast_mutex_unlock(&locklock);
    
    	lasttv.tv_sec = lasttv.tv_usec = 0;
    
    	for(i = 0 ; i < 32 ; i++)
    	{
    
    		j = (i + lock_ring_index_copy) % 32;
    
    		strftime(a,sizeof(a) - 1,"%m/%d/%Y %H:%M:%S",
    			localtime(&lock_ring_copy[j].tv.tv_sec));
    
    		if(lasttv.tv_sec)
    		{
    			diff = (lock_ring_copy[j].tv.tv_sec - lasttv.tv_sec)
    				* 1000000;
    
    			diff += (lock_ring_copy[j].tv.tv_usec - lasttv.tv_usec);
    		}
    		lasttv.tv_sec = lock_ring_copy[j].tv.tv_sec;
    		lasttv.tv_usec = lock_ring_copy[j].tv.tv_usec;
    
    		if (!lock_ring_copy[j].tv.tv_sec) continue;
    		if (lock_ring_copy[j].line < 0)
    		{
    			ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] UNLOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
    				i - 31,-lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
    		}
    		else
    		{
    			ast_log(LOG_NOTICE,"LOCKDEBUG [#%d] LOCK app_rpt.c:%d node %s pid %x diff %lld us at %s.%06d\n",
    				i - 31,lock_ring_copy[j].line,lock_ring_copy[j].rpt->name,(int) lock_ring_copy[j].lockthread.id,diff,a,(int)lock_ring_copy[j].tv.tv_usec);
    
    		}
    	}
    }
    
    
    static void _rpt_mutex_lock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
    {