[asterisk-commits] trunk r11146 - /trunk/apps/app_rpt.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Sat Feb 25 22:11:36 MST 2006


Author: jdixon
Date: Sat Feb 25 23:11:34 2006
New Revision: 11146

URL: http://svn.digium.com/view/asterisk?rev=11146&view=rev
Log:
Fixed nasty lockup bug and added command macros (not to be confused with
macro-oni).

Modified:
    trunk/apps/app_rpt.c

Modified: trunk/apps/app_rpt.c
URL: http://svn.digium.com/view/asterisk/trunk/apps/app_rpt.c?rev=11146&r1=11145&r2=11146&view=diff
==============================================================================
--- trunk/apps/app_rpt.c (original)
+++ trunk/apps/app_rpt.c Sat Feb 25 23:11:34 2006
@@ -20,8 +20,8 @@
 /*! \file
  *
  * \brief Radio Repeater / Remote Base program 
- *  version 0.39 12/19/05
- *
+ *  version 0.42 02/25/06
+ * 
  * \author Jim Dixon, WB6NIL <jim at lambdatel.com>
  *
  * \note Serious contributions by Steve RoDgers, WA6ZFT <hwstar at rodgers.sdcoxmail.com>
@@ -107,6 +107,9 @@
 /* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
 
 #define	MAXDTMF 32
+#define	MAXMACRO 2048
+#define	MACROTIME 100
+#define	MACROPTIME 500
 #define	DTMF_TIMEOUT 3
 
 #define	DISC_TIME 10000  /* report disc after 10 seconds of no connect */
@@ -123,6 +126,7 @@
 
 #define	NODES "nodes"
 #define MEMORY "memory"
+#define MACRO "macro"
 #define	FUNCTIONS "functions"
 #define TELEMETRY "telemetry"
 #define MORSE "morse"
@@ -147,7 +151,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};
+	TAILMSG, MACRO_NOTFOUND, MACRO_BUSY};
 
 enum {REM_SIMPLEX,REM_MINUS,REM_PLUS};
 
@@ -206,7 +210,7 @@
 #include "asterisk/say.h"
 #include "asterisk/localtime.h"
 
-static  char *tdesc = "Radio Repeater / Remote Base  version 0.39  12/19/2005";
+static  char *tdesc = "Radio Repeater / Remote Base  version 0.42  02/25/2006";
 
 static char *app = "Rpt";
 
@@ -247,7 +251,7 @@
 "            available to the phone user.\n"
 "\n";
 
-static int debug = 0;  /* Set this >0 for extra debug output */
+static int debug = 0;  /* FIXME Set this >0 for extra debug output */
 static int nrpts = 0;
 
 char *discstr = "!!DISCONNECT!!";
@@ -256,6 +260,7 @@
 
 struct	ast_config *cfg;
 
+STANDARD_LOCAL_USER;
 LOCAL_USER_DECL;
 
 #define	MSWAIT 200
@@ -362,15 +367,16 @@
 	char tonotify;
 	char enable;
 	char dtmfbuf[MAXDTMF];
+	char macrobuf[MAXMACRO];
 	char rem_dtmfbuf[MAXDTMF];
 	char cmdnode[50];
 	struct ast_channel *rxchannel,*txchannel;
 	struct ast_channel *pchannel,*txpchannel, *remchannel;
 	struct rpt_tele tele;
 	pthread_t rpt_call_thread,rpt_thread;
-	time_t rem_dtmf_time,dtmf_time_rem;
+	time_t dtmf_time,rem_dtmf_time,dtmf_time_rem;
 	int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer;
-	int mustid;
+	int mustid,tailid;
 	int politeid;
 	int dtmfidx,rem_dtmfidx;
 	long	retxtimer;
@@ -390,6 +396,7 @@
 	char funcchar;
 	char endchar;
 	char stopgen;
+	int macro_longest;
 	int phone_longestfunc;
 	int dphone_longestfunc;
 	int link_longestfunc;
@@ -403,8 +410,197 @@
 	int tailmessagen;
 	time_t disgorgetime;
 	time_t lastthreadrestarttime;
+	long	macrotimer;
+	char	*macro;
+	char	*startupmacro;
+	char	*memory;
 	char	nobusyout;
 } rpt_vars[MAXRPTS];	
+
+
+#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)
+{
+int	i;
+
+	for(i = 0; i < MAXLOCKTHREAD; i++)
+	{
+		if (lockthreads[i].id == id) return(&lockthreads[i]);
+	}
+	return(NULL);
+}
+
+static struct lockthread *put_lockthread(pthread_t id)
+{
+int	i;
+
+	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]);
+		}
+	}
+	return(NULL);
+}
+
+
+static void rpt_mutex_spew(void)
+{
+	struct by_lightning lock_ring_copy[32];
+	int lock_ring_index_copy;
+	int i,j;
+	long long diff;
+	char a[100];
+	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));
+		diff = 0;
+		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)
+{
+struct lockthread *t;
+pthread_t id;
+
+	id = pthread_self();
+	ast_mutex_lock(&locklock);
+	t = put_lockthread(id);
+	if (!t)
+	{
+		ast_mutex_unlock(&locklock);
+		return;
+	}
+	if (t->lockcount)
+	{
+		int lastline = t->lastlock;
+		ast_mutex_unlock(&locklock);
+		ast_log(LOG_NOTICE,"rpt_mutex_lock: Double lock request line %d node %s pid %x, last lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
+		rpt_mutex_spew();
+		return;
+	}
+	t->lastlock = line;
+	t->lockcount = 1;
+	gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
+	lock_ring[lock_ring_index].rpt = myrpt;
+	memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
+	lock_ring[lock_ring_index++].line = line;
+	if(lock_ring_index == 32)
+		lock_ring_index = 0;
+	ast_mutex_unlock(&locklock);
+	ast_mutex_lock(lockp);
+}
+
+
+static void _rpt_mutex_unlock(ast_mutex_t *lockp, struct rpt *myrpt, int line)
+{
+struct lockthread *t;
+pthread_t id;
+
+	id = pthread_self();
+	ast_mutex_lock(&locklock);
+	t = put_lockthread(id);
+	if (!t)
+	{
+		ast_mutex_unlock(&locklock);
+		return;
+	}
+	if (!t->lockcount)
+	{
+		int lastline = t->lastunlock;
+		ast_mutex_unlock(&locklock);
+		ast_log(LOG_NOTICE,"rpt_mutex_lock: Double un-lock request line %d node %s pid %x, last un-lock was line %d\n",line,myrpt->name,(int) t->id,lastline);
+		rpt_mutex_spew();
+		return;
+	}
+	t->lastunlock = line;
+	t->lockcount = 0;
+	gettimeofday(&lock_ring[lock_ring_index].tv, NULL);
+	lock_ring[lock_ring_index].rpt = myrpt;
+	memcpy(&lock_ring[lock_ring_index].lockthread,t,sizeof(struct lockthread));
+	lock_ring[lock_ring_index++].line = -line;
+	if(lock_ring_index == 32)
+		lock_ring_index = 0;
+	ast_mutex_unlock(&locklock);
+	ast_mutex_unlock(lockp);
+}
+
+#else  /* APP_RPT_LOCK_DEBUG */
+
+#define rpt_mutex_lock(x) ast_mutex_lock(x)
+#define rpt_mutex_unlock(x) ast_mutex_unlock(x)
+
+#endif  /* APP_RPT_LOCK_DEBUG */
 
 /*
 * CLI extensions
@@ -412,15 +608,32 @@
 
 /* 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_frog(int fd, int argc, char *argv[]);
 
 static char debug_usage[] =
 "Usage: rpt debug level {0-7}\n"
 "       Enables debug messages in app_rpt\n";
-                                                                                                                                
+
+static char dump_usage[] =
+"Usage: rpt dump <nodename>\n"
+"       Dumps struct debug info to log\n";
+
+static char frog_usage[] =
+"Usage: frog [warp_factor]\n"
+"       Performs frog-in-a-blender calculations (Jacobsen Corollary)\n";
+
 static struct ast_cli_entry  cli_debug =
-        { { "rpt", "debug", "level" }, rpt_do_debug, "Enable app_rpt debugging", debug_usage };
-
-
+        { { "rpt", "debug", "level" }, rpt_do_debug, 
+		"Enable app_rpt debugging", debug_usage };
+
+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_frog =
+        { { "frog" }, rpt_do_frog,
+		"Perform frog-in-a-blender calculations", frog_usage };
 
 /*
 * Telemetry defaults
@@ -460,6 +673,7 @@
 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
+static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
 /*
 * Function table
 */
@@ -470,7 +684,8 @@
 	{"autopatchdn", function_autopatchdn},
 	{"ilink", function_ilink},
 	{"status", function_status},
-	{"remote", function_remote}
+	{"remote", function_remote},
+	{"macro", function_macro}
 } ;
 	
 static int finddelim(char *str,char *strp[])
@@ -542,8 +757,49 @@
         debug = newlevel;                                                                                                                          
         return RESULT_SUCCESS;
 }
+
+/*
+* Dump rpt struct debugging onto console
+*/
                                                                                                                                  
-
+static int rpt_do_dump(int fd, int argc, char *argv[])
+{
+	int i;
+
+        if (argc != 3)
+                return RESULT_SHOWUSAGE;
+
+	for(i = 0; i < nrpts; i++)
+	{
+		if (!strcmp(argv[2],rpt_vars[i].name))
+		{
+			rpt_vars[i].disgorgetime = time(NULL) + 10; /* Do it 10 seconds later */
+		        ast_cli(fd, "app_rpt struct dump requested for node %s\n",argv[2]);
+		        return RESULT_SUCCESS;
+		}
+	}
+	return RESULT_FAILURE;
+}
+
+/*
+* Perform frong-in-a-blender calculations (Jacobsen Corollary) 
+*/
+                                                                                                                                 
+static int rpt_do_frog(int fd, int argc, char *argv[])
+{
+	double warpone = 75139293848.398696166028333356763;
+	double warpfactor = 1.0;
+
+        if (argc > 2) return RESULT_SHOWUSAGE;
+	if ((argc > 1) && (sscanf(argv[1],"%lf",&warpfactor) != 1))
+                return RESULT_SHOWUSAGE;
+
+        ast_cli(fd, "A frog in a blender with a base diameter of 3 inches going\n");
+        ast_cli(fd, "%lf RPM will be travelling at warp factor %lf,\n",
+		warpfactor * warpfactor * warpfactor * warpone,warpfactor);
+	ast_cli(fd,"based upon the Jacobsen Frog Corollary.\n");
+	return RESULT_FAILURE;
+}
 
 static int play_tone_pair(struct ast_channel *chan, int f1, int f2, int duration, int amplitude)
 {
@@ -1028,35 +1284,37 @@
 time_t t;
 struct tm localtm;
 
-
 	/* get a pointer to myrpt */
 	myrpt = mytele->rpt;
 
 	/* Snag copies of a few key myrpt variables */
-	ast_mutex_lock(&myrpt->lock);
+	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);
-	ast_mutex_unlock(&myrpt->lock);
-	
+	rpt_mutex_unlock(&myrpt->lock);
 	
 	/* allocate a pseudo-channel thru asterisk */
-	if (!(mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL)))
+	mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+	if (!mychannel)
 	{
 		fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
-		ast_mutex_lock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
 		remque((struct qelem *)mytele);
-		ast_mutex_unlock(&myrpt->lock);
+		ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
+		rpt_mutex_unlock(&myrpt->lock);
 		free(mytele);		
 		pthread_exit(NULL);
 	}
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	mytele->chan = mychannel; /* Save a copy of the channel so we can access it externally if need be */
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	
 	/* make a conference for the tx */
 	ci.chan = 0;
-	/* If there's an ID queued, only connect the ID audio to the local tx conference so 
-		linked systems can't hear it */
+	/* If there's an ID queued, or tail message queued, */
+	/* only connect the ID audio to the local tx conference so */
+	/* linked systems can't hear it */
 	ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) || 
 		(mytele->mode == TAILMSG)) ?
 		 	myrpt->txconf : myrpt->conf);
@@ -1065,9 +1323,10 @@
 	if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
 	{
 		ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
-		ast_mutex_lock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
 		remque((struct qelem *)mytele);
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
+		ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
 		free(mytele);		
 		ast_hangup(mychannel);
 		pthread_exit(NULL);
@@ -1110,6 +1369,16 @@
 		wait_interval(myrpt, DLY_TELEM, mychannel);
 		res = telem_lookup(mychannel, myrpt->name, "functcomplete");
 		break;
+	    case MACRO_NOTFOUND:
+		/* wait a little bit */
+		wait_interval(myrpt, DLY_TELEM, mychannel);
+		res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
+		break;
+	    case MACRO_BUSY:
+		/* wait a little bit */
+		wait_interval(myrpt, DLY_TELEM, mychannel);
+		res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
+		break;
 	    case UNKEY:
 
 		/*
@@ -1117,9 +1386,9 @@
 		*/
 
 		x = get_wait_interval(myrpt, DLY_UNKEY);
-		ast_mutex_lock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
 		myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 
 		/*
 		* If there's one already queued, don't do another
@@ -1129,12 +1398,12 @@
 		unkeys_queued = 0;
                 if (tlist != &myrpt->tele)
                 {
-                        ast_mutex_lock(&myrpt->lock);
+                        rpt_mutex_lock(&myrpt->lock);
                         while(tlist != &myrpt->tele){
                                 if (tlist->mode == UNKEY) unkeys_queued++;
                                 tlist = tlist->next;
                         }
-                        ast_mutex_unlock(&myrpt->lock);
+                        rpt_mutex_unlock(&myrpt->lock);
 		}
 		if( unkeys_queued > 1){
 			imdone = 1;
@@ -1143,7 +1412,6 @@
 
 		/* Wait for the telemetry timer to expire */
 		/* Periodically check the timer since it can be re-initialized above */
-
 		while(myrpt->unkeytocttimer)
 		{
 			int ctint;
@@ -1152,15 +1420,14 @@
 			else
 				ctint = myrpt->unkeytocttimer;
 			ast_safe_sleep(mychannel, ctint);
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			if(myrpt->unkeytocttimer < ctint)
 				myrpt->unkeytocttimer = 0;
 			else
 				myrpt->unkeytocttimer -= ctint;
-			ast_mutex_unlock(&myrpt->lock);
-		}
-	
-
+			rpt_mutex_unlock(&myrpt->lock);
+		}
+	
 		/*
 		* Now, the carrier on the rptr rx should be gone. 
 		* If it re-appeared, then forget about sending the CT
@@ -1176,7 +1443,7 @@
 		l = myrpt->links.next;
 		if (l != &myrpt->links)
 		{
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			while(l != &myrpt->links)
 			{
 				if (l->name[0] == '0')
@@ -1191,7 +1458,7 @@
 				}
 				l = l->next;
 			}
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 		}
 		if (haslink)
 		{
@@ -1217,7 +1484,6 @@
 			if(res)
 			 	ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);		
 		}	
-			
 		if (hasremote && (!myrpt->cmdnode[0]))
 		{
 			/* set for all to hear */
@@ -1228,9 +1494,10 @@
 			if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
 			{
 				ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
-				ast_mutex_lock(&myrpt->lock);
+				rpt_mutex_lock(&myrpt->lock);
 				remque((struct qelem *)mytele);
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
+				ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
 				free(mytele);		
 				ast_hangup(mychannel);
 				pthread_exit(NULL);
@@ -1301,7 +1568,7 @@
 		hastx = 0;
 		linkbase.next = &linkbase;
 		linkbase.prev = &linkbase;
-		ast_mutex_lock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
 		/* make our own list of links */
 		l = myrpt->links.next;
 		while(l != &myrpt->links)
@@ -1310,12 +1577,14 @@
 			{
 				l = l->next;
 				continue;
-			}			
-			if (!(m = ast_malloc(sizeof(*m))))
+			}
+			m = malloc(sizeof(struct rpt_link));
+			if (!m)
 			{
-				ast_mutex_lock(&myrpt->lock);
+				ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
 				remque((struct qelem *)mytele);
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
+				ast_log(LOG_NOTICE,"Telemetry thread aborted at line %d, mode: %d\n",__LINE__, mytele->mode); /*@@@@@@@@@@@*/
 				free(mytele);		
 				ast_hangup(mychannel);
 				pthread_exit(NULL);
@@ -1325,7 +1594,7 @@
 			insque((struct qelem *)m,(struct qelem *)linkbase.next);
 			l = l->next;
 		}
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
 		if (!res) 
 			res = ast_waitstream(mychannel, "");
@@ -1534,7 +1803,7 @@
 		}
 	}
 	ast_stopstream(mychannel);
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	if (mytele->mode == TAILMSG)
 	{
 		if (!res)
@@ -1548,9 +1817,20 @@
 		}
 	}
 	remque((struct qelem *)mytele);
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	free(mytele);		
 	ast_hangup(mychannel);
+#ifdef  APP_RPT_LOCK_DEBUG
+	{
+		struct lockthread *t;
+
+		sleep(5);
+		ast_mutex_lock(&locklock);
+		t = get_lockthread(pthread_self());
+		if (t) memset(t,0,sizeof(struct lockthread));
+		ast_mutex_unlock(&locklock);
+	}			
+#endif
 	pthread_exit(NULL);
 }
 
@@ -1558,16 +1838,21 @@
 {
 struct rpt_tele *tele;
 struct rpt_link *mylink = (struct rpt_link *) data;
+int res;
 pthread_attr_t attr;
-	
-	if (!(tele = ast_calloc(1, sizeof(*tele))))
-	{
+
+	tele = malloc(sizeof(struct rpt_tele));
+	if (!tele)
+	{
+		ast_log(LOG_WARNING, "Unable to allocate memory\n");
 		pthread_exit(NULL);
 		return;
 	}
+	/* zero it out */
+	memset((char *)tele,0,sizeof(struct rpt_tele));
 	tele->rpt = myrpt;
 	tele->mode = mode;
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)){
 		memset(&tele->mylink,0,sizeof(struct rpt_link));
 		if (mylink){
@@ -1578,11 +1863,12 @@
 		strncpy(tele->param, (char *) data, TELEPARAMSIZE - 1);
 		tele->param[TELEPARAMSIZE - 1] = 0;
 	}
-	insque((struct qelem *)tele,(struct qelem *)myrpt->tele.next); 
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
         pthread_attr_init(&attr);
         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-	ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
+	res = ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
+	if(res < 0)
+		ast_log(LOG_WARNING, "Could not create telemetry thread: %s",strerror(res));
 	return;
 }
 
@@ -1597,7 +1883,8 @@
 
 	myrpt->mydtmf = 0;
 	/* allocate a pseudo-channel thru asterisk */
-	if (!(mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL)))
+	mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+	if (!mychannel)
 	{
 		fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
 		pthread_exit(NULL);
@@ -1615,7 +1902,8 @@
 		pthread_exit(NULL);
 	}
 	/* allocate a pseudo-channel thru asterisk */
-	if (!(genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL)))
+	genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+	if (!genchannel)
 	{
 		fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
 		ast_hangup(mychannel);
@@ -1681,9 +1969,9 @@
 		{
 			ast_hangup(mychannel);
 			ast_hangup(genchannel);
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			myrpt->callmode = 0;
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			pthread_exit(NULL);
 		}
 	}
@@ -1694,9 +1982,9 @@
 	{
 		ast_hangup(mychannel);
 		ast_hangup(genchannel);
-		ast_mutex_lock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
 		myrpt->callmode = 0;
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		pthread_exit(NULL);			
 	}
 
@@ -1730,23 +2018,23 @@
 		ast_log(LOG_WARNING, "Unable to start PBX!!\n");
 		ast_hangup(mychannel);
 		ast_hangup(genchannel);
-		ast_mutex_lock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
 	 	myrpt->callmode = 0;
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		pthread_exit(NULL);
 	}
 	usleep(10000);
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	myrpt->callmode = 3;
 	while(myrpt->callmode)
 	{
 		if ((!mychannel->pbx) && (myrpt->callmode != 4))
 		{
 			myrpt->callmode = 4;
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			/* start congestion tone */
 			tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 		}
 		if (myrpt->mydtmf)
 		{
@@ -1757,22 +2045,22 @@
 			wf.data = NULL;
 			wf.datalen = 0;
 			wf.samples = 0;
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			ast_write(genchannel,&wf); 
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			myrpt->mydtmf = 0;
 		}
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		usleep(MSWAIT * 1000);
-		ast_mutex_lock(&myrpt->lock);
-	}
-	ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_lock(&myrpt->lock);
+	}
+	rpt_mutex_unlock(&myrpt->lock);
 	tone_zone_play_tone(genchannel->fds[0],-1);
 	if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
 	ast_hangup(genchannel);
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	myrpt->callmode = 0;
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	pthread_exit(NULL);
 }
 
@@ -1857,7 +2145,7 @@
 			s = tmp;
 			s1 = strsep(&s,",");
 			s2 = strsep(&s,",");
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			l = myrpt->links.next;
 			/* try to find this one in queue */
 			while(l != &myrpt->links){
@@ -1877,7 +2165,7 @@
 				strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
 				l->retries = MAX_RETRIES + 1;
 				l->disced = 1;
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
 				wf.frametype = AST_FRAME_TEXT;
 				wf.subclass = 0;
 				wf.offset = 0;
@@ -1894,7 +2182,7 @@
 				rpt_telemetry(myrpt, COMPLETE, NULL);
 				return DC_COMPLETE;
 			}
-			ast_mutex_unlock(&myrpt->lock);	
+			rpt_mutex_unlock(&myrpt->lock);	
 			return DC_COMPLETE;
 		case 2: /* Link Monitor */
 			if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
@@ -1909,7 +2197,7 @@
 			s = tmp;
 			s1 = strsep(&s,",");
 			s2 = strsep(&s,",");
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			l = myrpt->links.next;
 			/* try to find this one in queue */
 			while(l != &myrpt->links){
@@ -1928,24 +2216,27 @@
 			{
 				/* if already in this mode, just ignore */
 				if ((!l->mode) || (!l->chan)) {
-					ast_mutex_unlock(&myrpt->lock);
+					rpt_mutex_unlock(&myrpt->lock);
 					rpt_telemetry(myrpt,REMALREADY,NULL);
 					return DC_COMPLETE;
 					
 				}
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
 				if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
 				l->retries = MAX_RETRIES + 1;
 				l->disced = 2;
 				modechange = 1;
 			} else
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
 			strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
-			/* establish call in monitor mode */			
-			if (!(l = ast_calloc(1, sizeof(*l)))) {
+			/* establish call in monitor mode */
+			l = malloc(sizeof(struct rpt_link));
+			if (!l){
+				ast_log(LOG_WARNING, "Unable to malloc\n");
 				return DC_ERROR;
 			}
 			/* zero the silly thing */
+			memset((char *)l,0,sizeof(struct rpt_link));
 			snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
 			tele = strchr(deststr,'/');
 			if (!tele){
@@ -1981,7 +2272,8 @@
 				return DC_ERROR;
 			}
 			/* allocate a pseudo-channel thru asterisk */
-			if (!(l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL))) {
+			l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+			if (!l->pchan){
 				fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
 				ast_hangup(l->chan);
 				free(l);
@@ -2002,10 +2294,10 @@
 				free(l);
 				return DC_ERROR;
 			}
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			/* insert at end of queue */
 			insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			rpt_telemetry(myrpt,COMPLETE,NULL);
 			return DC_COMPLETE;
 		case 3: /* Link transceive */
@@ -2021,7 +2313,7 @@
 			s = tmp;
 			s1 = strsep(&s,",");
 			s2 = strsep(&s,",");
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			l = myrpt->links.next;
 			/* try to find this one in queue */
 			while(l != &myrpt->links){
@@ -2039,22 +2331,26 @@
 			if (l != &myrpt->links){ 
 				/* if already in this mode, just ignore */
 				if ((l->mode) || (!l->chan)) {
-					ast_mutex_unlock(&myrpt->lock);
+					rpt_mutex_unlock(&myrpt->lock);
 					rpt_telemetry(myrpt, REMALREADY, NULL);
 					return DC_COMPLETE;
 				}
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
 				if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
 				l->retries = MAX_RETRIES + 1;
 				l->disced = 2;
 				modechange = 1;
 			} else
-				ast_mutex_unlock(&myrpt->lock);
+				rpt_mutex_unlock(&myrpt->lock);
 			strncpy(myrpt->lastlinknode,digitbuf,MAXNODESTR - 1);
 			/* establish call in tranceive mode */
-			if (!(l = ast_calloc(1, sizeof(*l)))) {
+			l = malloc(sizeof(struct rpt_link));
+			if (!l){
+				ast_log(LOG_WARNING, "Unable to malloc\n");
 				return(DC_ERROR);
 			}
+			/* zero the silly thing */
+			memset((char *)l,0,sizeof(struct rpt_link));
 			l->mode = 1;
 			l->outbound = 1;
 			strncpy(l->name, digitbuf, MAXNODESTR - 1);
@@ -2092,7 +2388,8 @@
 				return DC_ERROR;
 			}
 			/* allocate a pseudo-channel thru asterisk */
-			if (!(l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL))) {
+			l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
+			if (!l->pchan){
 				fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
 				ast_hangup(l->chan);
 				free(l);
@@ -2113,10 +2410,10 @@
 				free(l);
 				return DC_ERROR;
 			}
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			/* insert at end of queue */
 			insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			rpt_telemetry(myrpt,COMPLETE,NULL);
 			return DC_COMPLETE;
 		case 4: /* Enter Command Mode */
@@ -2141,10 +2438,10 @@
 				break;
 			
 			}
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			strcpy(myrpt->lastlinknode,digitbuf);
 			strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			rpt_telemetry(myrpt, REMGO, NULL);	
 			return DC_COMPLETE;
 			
@@ -2186,7 +2483,7 @@
 	if(debug)
 		printf("@@@@ Autopatch up\n");
 
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	
 	/* if on call, force * into current audio stream */
 	
@@ -2194,13 +2491,13 @@
 		myrpt->mydtmf = myrpt->funcchar;
 	}
 	if (myrpt->callmode){
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		return DC_COMPLETE;
 	}
 	myrpt->callmode = 1;
 	myrpt->cidx = 0;
 	myrpt->exten[myrpt->cidx] = 0;
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	pthread_attr_init(&attr);
 	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
 	ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *) myrpt);
@@ -2219,15 +2516,15 @@
 	if(debug)
 		printf("@@@@ Autopatch down\n");
 		
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	
 	if (!myrpt->callmode){
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		return DC_COMPLETE;
 	}
 	
 	myrpt->callmode = 0;
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	rpt_telemetry(myrpt, TERM, NULL);
 	return DC_COMPLETE;
 }
@@ -2239,10 +2536,9 @@
 static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
 {
 
-	if(!param)
+	if (!param)
 		return DC_ERROR;
-		
-			
+
 	if (!myrpt->enable)
 		return DC_ERROR;
 
@@ -2262,6 +2558,53 @@
 			return DC_ERROR;
 	}
 	return DC_INDETERMINATE;
+}
+
+/*
+*  Macro-oni (without Salami)
+*/
+
+static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
+{
+
+char	*val;
+int	i;
+struct	ast_channel *mychannel;
+
+	if ((!myrpt->remote) && (!myrpt->enable))
+		return DC_ERROR;
+
+	if(debug) 
+		printf("@@@@ macro-oni param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
+	
+	mychannel = myrpt->remchannel;
+
+	if(strlen(digitbuf) < 1) /* needs 1 digit */
+		return DC_INDETERMINATE;
+			
+	for(i = 0 ; i < digitbuf[i] ; i++) {
+		if((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+			return DC_ERROR;
+	}
+   
+	if (*digitbuf == '0') val = myrpt->startupmacro;
+	else val = ast_variable_retrieve(cfg, myrpt->macro, digitbuf);
+	/* param was 1 for local buf */
+	if (!val){
+		rpt_telemetry(myrpt, MACRO_NOTFOUND, NULL);
+		return DC_COMPLETE;
+	}			
+	rpt_mutex_lock(&myrpt->lock);
+	if ((MAXMACRO - strlen(myrpt->macrobuf)) < strlen(val))
+	{
+		rpt_mutex_unlock(&myrpt->lock);
+		rpt_telemetry(myrpt, MACRO_BUSY, NULL);
+		return DC_ERROR;
+	}
+	myrpt->macrotimer = MACROTIME;
+	strncat(myrpt->macrobuf,val,MAXMACRO - 1);
+	rpt_mutex_unlock(&myrpt->lock);
+	return DC_COMPLETE;	
 }
 
 /*
@@ -2476,7 +2819,7 @@
 		}
 		return;
 	}
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	if (c == myrpt->endchar) myrpt->stopgen = 1;
 	if (myrpt->callmode == 1)
 	{
@@ -2486,7 +2829,9 @@
 		if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
 		{
 			myrpt->callmode = 2;
+			rpt_mutex_unlock(&myrpt->lock);
 			rpt_telemetry(myrpt,PROC,NULL); 
+			rpt_mutex_lock(&myrpt->lock);
 		}
 		/* if can continue, do so */
 		if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 
@@ -2504,7 +2849,7 @@
 		myrpt->rem_dtmfidx = 0;
 		myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
 		time(&myrpt->rem_dtmf_time);
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		return;
 	} 
 	else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
@@ -2515,10 +2860,10 @@
 			myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
 			myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
 			
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
 			res = collect_function_digits(myrpt, cmd, SOURCE_LNK, mylink);
-			ast_mutex_lock(&myrpt->lock);
+			rpt_mutex_lock(&myrpt->lock);
 			
 			switch(res){
 
@@ -2547,7 +2892,7 @@
 		}
 
 	}
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	return;
 }
 
@@ -2558,13 +2903,13 @@
 char	cmd[300];
 int	res;
 
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	if (c == myrpt->endchar)
 	{
 		if (mylink->lastrx)
 		{
 			mylink->lastrx = 0;
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			return;
 		}
 		myrpt->stopgen = 1;
@@ -2573,15 +2918,14 @@
 			myrpt->cmdnode[0] = 0;
 			myrpt->dtmfidx = -1;
 			myrpt->dtmfbuf[0] = 0;
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			rpt_telemetry(myrpt,COMPLETE,NULL);
-			ast_mutex_unlock(&myrpt->lock);
 			return;
 		}
 	}
 	if (myrpt->cmdnode[0])
 	{
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		send_link_dtmf(myrpt,c);
 		return;
 	}
@@ -2593,7 +2937,9 @@
 		if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
 		{
 			myrpt->callmode = 2;
+			rpt_mutex_unlock(&myrpt->lock);
 			rpt_telemetry(myrpt,PROC,NULL); 
+			rpt_mutex_lock(&myrpt->lock);
 		}
 		/* if can continue, do so */
 		if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL)) 
@@ -2611,7 +2957,7 @@
 		myrpt->rem_dtmfidx = 0;
 		myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
 		time(&myrpt->rem_dtmf_time);
-		ast_mutex_unlock(&myrpt->lock);
+		rpt_mutex_unlock(&myrpt->lock);
 		return;
 	} 
 	else if ((c != myrpt->endchar) && (myrpt->rem_dtmfidx >= 0))
@@ -2622,11 +2968,25 @@
 			myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx++] = c;
 			myrpt->rem_dtmfbuf[myrpt->rem_dtmfidx] = 0;
 			
-			ast_mutex_unlock(&myrpt->lock);
+			rpt_mutex_unlock(&myrpt->lock);
 			strncpy(cmd, myrpt->rem_dtmfbuf, sizeof(cmd) - 1);
-			res = collect_function_digits(myrpt, cmd, 
-				((mylink->phonemode == 2) ? SOURCE_DPHONE : SOURCE_PHONE), mylink);
-			ast_mutex_lock(&myrpt->lock);
+			switch(mylink->phonemode)
+			{
+			    case 1:
+				res = collect_function_digits(myrpt, cmd, 
+					SOURCE_PHONE, mylink);
+				break;
+			    case 2:
+				res = collect_function_digits(myrpt, cmd, 
+					SOURCE_DPHONE,mylink);
+				break;
+			    default:
+				res = collect_function_digits(myrpt, cmd, 
+					SOURCE_LNK, mylink);
+				break;
+			}
+
+			rpt_mutex_lock(&myrpt->lock);
 			
 			switch(res){
 
@@ -2659,7 +3019,7 @@
 		}
 
 	}
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	return;
 }
 
@@ -3695,7 +4055,7 @@
 					return DC_ERROR;
 			}
 	    
-			val = ast_variable_retrieve(cfg, MEMORY, digitbuf);
+			val = ast_variable_retrieve(cfg, myrpt->memory, digitbuf);
 			if (!val){
 				if (ast_safe_sleep(mychannel,1000) == -1)
 					return DC_ERROR;
@@ -4527,10 +4887,10 @@
 		return -1;
 	}
 
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	/* remove from queue */
 	remque((struct qelem *) l);
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	strncpy(tmp,val,sizeof(tmp) - 1);
 	s = tmp;
 	s1 = strsep(&s,",");
@@ -4566,37 +4926,179 @@
 				deststr,tele,l->chan->name);
 		return -1;
 	}
-	ast_mutex_lock(&myrpt->lock);
+	rpt_mutex_lock(&myrpt->lock);
 	/* put back in queue queue */
 	insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
-	ast_mutex_unlock(&myrpt->lock);
+	rpt_mutex_unlock(&myrpt->lock);
 	ast_log(LOG_NOTICE,"Reconnect Attempt to %s in process\n",l->name);
 	return 0;
 }
 
+/* 0 return=continue, 1 return = break, -1 return = error */
+static void local_dtmf_helper(struct rpt *myrpt,char c)
+{
+int	res;
+pthread_attr_t	attr;
+char	cmd[MAXDTMF+1] = "";
+
+	if (c == myrpt->endchar)
+	{
+	/* if in simple mode, kill autopatch */
+		if (myrpt->simple && myrpt->callmode)
+		{
+			rpt_mutex_lock(&myrpt->lock);
+			myrpt->callmode = 0;
+			rpt_mutex_unlock(&myrpt->lock);
+			rpt_telemetry(myrpt,TERM,NULL);
+			return;
+		}
+		rpt_mutex_lock(&myrpt->lock);
+		myrpt->stopgen = 1;
+		if (myrpt->cmdnode[0])
+		{
+			myrpt->cmdnode[0] = 0;
+			myrpt->dtmfidx = -1;
+			myrpt->dtmfbuf[0] = 0;
+			rpt_mutex_unlock(&myrpt->lock);
+			rpt_telemetry(myrpt,COMPLETE,NULL);
+		} else rpt_mutex_unlock(&myrpt->lock);
+		return;
+	}
+	rpt_mutex_lock(&myrpt->lock);
+	if (myrpt->cmdnode[0])
+	{
+		rpt_mutex_unlock(&myrpt->lock);
+		send_link_dtmf(myrpt,c);
+		return;
+	}
+	if (!myrpt->simple)
+	{
+		if (c == myrpt->funcchar)
+		{
+			myrpt->dtmfidx = 0;
+			myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
+			rpt_mutex_unlock(&myrpt->lock);
+			time(&myrpt->dtmf_time);
+			return;
+		} 
+		else if ((c != myrpt->endchar) && (myrpt->dtmfidx >= 0))
+		{
+			time(&myrpt->dtmf_time);
+			
+			if (myrpt->dtmfidx < MAXDTMF)
+			{
+				myrpt->dtmfbuf[myrpt->dtmfidx++] = c;
+				myrpt->dtmfbuf[myrpt->dtmfidx] = 0;
+				
+				strncpy(cmd, myrpt->dtmfbuf, sizeof(cmd) - 1);
+				
+				rpt_mutex_unlock(&myrpt->lock);
+				res = collect_function_digits(myrpt, cmd, SOURCE_RPT, NULL);
+				rpt_mutex_lock(&myrpt->lock);
+				switch(res){
+				    case DC_INDETERMINATE:
+					break;
+				    case DC_REQ_FLUSH:
+					myrpt->dtmfidx = 0;
+					myrpt->dtmfbuf[0] = 0;
+					break;
+				    case DC_COMPLETE:
+					myrpt->dtmfbuf[0] = 0;
+					myrpt->dtmfidx = -1;
+					myrpt->dtmf_time = 0;
+					break;
+
+				    case DC_ERROR:
+				    default:
+					myrpt->dtmfbuf[0] = 0;
+					myrpt->dtmfidx = -1;
+					myrpt->dtmf_time = 0;
+					break;
+				}
+				if(res != DC_INDETERMINATE) {
+					rpt_mutex_unlock(&myrpt->lock);
+					return;
+				}
+			} 
+		}
+	}
+	else /* if simple */
+	{
+		if ((!myrpt->callmode) && (c == myrpt->funcchar))
+		{
+			myrpt->callmode = 1;
+			myrpt->cidx = 0;
+			myrpt->exten[myrpt->cidx] = 0;
+			rpt_mutex_unlock(&myrpt->lock);
+		        pthread_attr_init(&attr);
+		        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+			ast_pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
+			return;
+		}
+	}
+	if (myrpt->callmode == 1)
+	{
+		myrpt->exten[myrpt->cidx++] = c;
+		myrpt->exten[myrpt->cidx] = 0;
+		/* if this exists */
+		if (ast_exists_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+		{
+			myrpt->callmode = 2;
+			rpt_mutex_unlock(&myrpt->lock);
+			rpt_telemetry(myrpt,PROC,NULL); 
+			return;
+		}
+		/* if can continue, do so */
+		if (!ast_canmatch_extension(myrpt->pchannel,myrpt->ourcontext,myrpt->exten,1,NULL))
+		{
+			/* call has failed, inform user */
+			myrpt->callmode = 4;
+		}
+		rpt_mutex_unlock(&myrpt->lock);
+		return;
+	}
+	if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
+	{
+		myrpt->mydtmf = c;
+	}
+	rpt_mutex_unlock(&myrpt->lock);
+	return;
+}
+
+
+/* place an ID event in the telemetry queue */
+
+static void queue_id(struct rpt *myrpt)
+{
+	myrpt->mustid = myrpt->tailid = 0;
+	myrpt->idtimer = myrpt->idtime; /* Reset our ID timer */
+	rpt_mutex_unlock(&myrpt->lock);
+	rpt_telemetry(myrpt,ID,NULL);
+	rpt_mutex_lock(&myrpt->lock);
+}
+
+
 /* single thread with one file (request) to dial */
 static void *rpt(void *this)
 {
 struct	rpt *myrpt = (struct rpt *)this;
-char *tele,*idtalkover;
-int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res, tailmessagequeued;
+char *tele,*idtalkover,c;
+int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,nonidentqueued,tailmessagequeued,ctqueued;
 struct ast_channel *who;
 ZT_CONFINFO ci;  /* conference info */
-time_t	dtmf_time,t;
+time_t	t;
 struct rpt_link *l,*m;
 struct rpt_tele *telem;
-pthread_attr_t attr;
 char tmpstr[300];
-char cmd[MAXDTMF+1] = "";
-
-
-	ast_mutex_lock(&myrpt->lock);
+
+
+	rpt_mutex_lock(&myrpt->lock);

[... 1144 lines stripped ...]


More information about the asterisk-commits mailing list