aboutsummaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
authorjim <jim@f38db490-d61c-443f-a65b-d21fe96a405b>2004-08-21 21:41:54 +0000
committerjim <jim@f38db490-d61c-443f-a65b-d21fe96a405b>2004-08-21 21:41:54 +0000
commit0f3875cebed8bb64cffe2d4084c77f6a3b672a6b (patch)
tree8df459aaad31df54755b315809e231b6af6925dd /apps
parent94057171acf1f336b5f2655a3ec1f8746fa7feb4 (diff)
Made some what turned out to be several changes to allow for radio channels
to be handled properly in the case of an Alarm state on their span. git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3631 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps')
-rwxr-xr-xapps/app_rpt.c222
1 files changed, 185 insertions, 37 deletions
diff --git a/apps/app_rpt.c b/apps/app_rpt.c
index 73e98a685..5c3b2550f 100755
--- a/apps/app_rpt.c
+++ b/apps/app_rpt.c
@@ -3,7 +3,7 @@
* Asterisk -- A telephony toolkit for Linux.
*
* Radio Repeater / Remote Base program
- * version 0.14 8/15/04
+ * version 0.15 8/21/04
*
* See http://www.zapatatelephony.org/app_rpt.html
*
@@ -103,6 +103,8 @@ enum {REM_LOWPWR,REM_MEDPWR,REM_HIPWR};
enum {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE};
enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT};
+enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
+
#include <asterisk/utils.h>
#include <asterisk/lock.h>
#include <asterisk/file.h>
@@ -114,7 +116,6 @@ enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT};
#include <asterisk/translate.h>
#include <asterisk/options.h>
#include <asterisk/config.h>
-#include <asterisk/utils.h>
#include <asterisk/say.h>
#include <asterisk/localtime.h>
#include <stdio.h>
@@ -136,7 +137,7 @@ enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT};
#include <tonezone.h>
#include <linux/zaptel.h>
-static char *tdesc = "Radio Repeater / Remote Base version 0.14 08/15/2004";
+static char *tdesc = "Radio Repeater / Remote Base version 0.15 08/21/2004";
static char *app = "Rpt";
static char *synopsis = "Radio Repeater/Remote Base Control System";
@@ -160,6 +161,7 @@ LOCAL_USER_DECL;
#define IDTIME 300000
#define MAXRPTS 20
#define POLITEID 30000
+#define FUNCTDELAY 1500
static pthread_t rpt_master_thread;
@@ -621,20 +623,34 @@ static int telem_any(struct ast_channel *chan, char *entry)
* 4 types of telemtry are handled: Morse ID, Morse Message, Tone Sequence, and a File containing a recording.
*/
-static int telem_lookup(struct ast_channel *chan, char *name)
+static int telem_lookup(struct ast_channel *chan, char *node, char *name)
{
int res;
int i;
char *entry;
+ char *telemetry;
+ char *telemetry_save;
res = 0;
+ telemetry_save = NULL;
entry = NULL;
+ /* Retrieve the section name for telemetry from the node section */
+
+ telemetry = ast_variable_retrieve(cfg, node, TELEMETRY);
+ if(telemetry){
+ telemetry_save = ast_strdupa(telemetry);
+ if(!telemetry_save){
+ ast_log(LOG_WARNING,"ast_strdupa() failed in telem_lookup()\n");
+ return res;
+ }
+ entry = ast_variable_retrieve(cfg, telemetry_save, name);
+ }
+
/* Try to look up the telemetry name */
- entry = ast_variable_retrieve(cfg, TELEMETRY, name);
if(!entry){
/* Telemetry name wasn't found in the config file, use the default */
for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){
@@ -651,6 +667,67 @@ static int telem_lookup(struct ast_channel *chan, char *name)
return res;
}
+/*
+* Wait a configurable interval of time
+*/
+
+
+static void wait_interval(struct rpt *myrpt, int type)
+{
+ int interval;
+ char *wait_times;
+ char *wait_times_save;
+
+ wait_times_save = NULL;
+ wait_times = ast_variable_retrieve(cfg, myrpt->name, "wait_times");
+
+ if(wait_times){
+ wait_times_save = ast_strdupa(wait_times);
+ if(!wait_times_save){
+ ast_log(LOG_WARNING, "Out of memory in wait_interval()\n");
+ wait_times = NULL;
+ }
+ }
+
+ switch(type){
+ case DLY_TELEM:
+ if(wait_times)
+ interval = retrieve_astcfgint(wait_times_save, "telemwait", 500, 5000, 1000);
+ else
+ interval = 1000;
+ break;
+
+ case DLY_ID:
+ if(wait_times)
+ interval = retrieve_astcfgint(wait_times_save, "idwait",250,5000,500);
+ else
+ interval = 500;
+ break;
+
+ case DLY_UNKEY:
+ if(wait_times)
+ interval = retrieve_astcfgint(wait_times_save, "unkeywait",500,5000,1000);
+ else
+ interval = 1000;
+ break;
+
+ case DLY_CALLTERM:
+ if(wait_times)
+ interval = retrieve_astcfgint(wait_times_save, "calltermwait",500,5000,1500);
+ else
+ interval = 1500;
+ break;
+
+ default:
+ return;
+ }
+
+ usleep(1000 * interval);
+ return;
+}
+
+
+
static void *rpt_tele_thread(void *this)
{
ZT_CONFINFO ci; /* conference info */
@@ -713,8 +790,7 @@ struct tm localtm;
case ID:
case ID1:
/* wait a bit */
- usleep(500000);
-
+ wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM);
res = telem_any(mychannel, ident);
imdone=1;
@@ -730,22 +806,22 @@ struct tm localtm;
case PROC:
/* wait a little bit longer */
- usleep(1500000);
+ wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
break;
case TERM:
/* wait a little bit longer */
- usleep(1500000);
+ wait_interval(myrpt, DLY_CALLTERM);
res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
break;
case COMPLETE:
/* wait a little bit */
- usleep(1000000);
- res = telem_lookup(mychannel, "functcomplete");
+ wait_interval(myrpt, DLY_TELEM);
+ res = telem_lookup(mychannel, myrpt->name, "functcomplete");
break;
case UNKEY:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_UNKEY);
hastx = 0;
@@ -760,7 +836,7 @@ struct tm localtm;
}
ast_mutex_unlock(&myrpt->lock);
- res = telem_lookup(mychannel,(!hastx) ? "remotemon" : "remotetx");
+ res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
if(res)
ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
@@ -769,7 +845,7 @@ struct tm localtm;
if (myrpt->cmdnode[0])
{
ast_safe_sleep(mychannel,200);
- res = telem_lookup(mychannel, "cmdmode");
+ res = telem_lookup(mychannel, myrpt->name, "cmdmode");
if(res)
ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
@@ -777,7 +853,7 @@ struct tm localtm;
}
else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
ct_copy = ast_strdupa(ct);
- res = telem_lookup(mychannel, ct_copy);
+ res = telem_lookup(mychannel, myrpt->name, ct_copy);
if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
@@ -786,7 +862,7 @@ struct tm localtm;
break;
case REMDISC:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
@@ -799,22 +875,22 @@ struct tm localtm;
break;
case REMALREADY:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
break;
case REMNOTFOUND:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
break;
case REMGO:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
break;
case CONNECTED:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
@@ -836,7 +912,7 @@ struct tm localtm;
break;
case STATUS:
/* wait a little bit */
- usleep(1000000);
+ wait_interval(myrpt, DLY_TELEM);
hastx = 0;
linkbase.next = &linkbase;
linkbase.prev = &linkbase;
@@ -936,7 +1012,7 @@ struct tm localtm;
break;
case STATS_TIME:
- usleep(1000000); /* Wait a little bit */
+ wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
t = time(NULL);
ast_localtime(&t, &localtm, NULL);
/* Say the phase of the day is before the time */
@@ -970,7 +1046,7 @@ struct tm localtm;
break;
if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
break;
- usleep(1000000); /* Wait a little bit */
+ wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
/* Say "version" */
if (sayfile(mychannel,"rpt/version") == -1)
{
@@ -998,7 +1074,7 @@ struct tm localtm;
imdone = 1;
break;
case ARB_ALPHA:
- usleep(1000000); /* Wait a little bit */
+ wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
if(mytele->param)
saycharstr(mychannel, mytele->param);
imdone = 1;
@@ -2666,7 +2742,7 @@ int seq,res;
ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
}
if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1;
- res = telem_lookup(myrpt->remchannel,"functcomplete");
+ res = telem_lookup(myrpt->remchannel, myrpt->name, "functcomplete");
if (!myrpt->remoterx)
{
ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
@@ -2686,11 +2762,13 @@ time_t dtmf_time,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);
- tele = strchr(myrpt->rxchanname,'/');
+ strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
+ tele = strchr(tmpstr,'/');
if (!tele)
{
fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname);
@@ -2698,9 +2776,16 @@ char cmd[MAXDTMF+1] = "";
pthread_exit(NULL);
}
*tele++ = 0;
- myrpt->rxchannel = ast_request(myrpt->rxchanname,AST_FORMAT_SLINEAR,tele);
+ myrpt->rxchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele);
if (myrpt->rxchannel)
{
+ if (myrpt->rxchannel->_state == AST_STATE_BUSY)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
+ ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
ast_set_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
myrpt->rxchannel->whentohangup = 0;
@@ -2708,8 +2793,14 @@ char cmd[MAXDTMF+1] = "";
myrpt->rxchannel->data = "(Repeater Rx)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n",
- myrpt->rxchanname,tele,myrpt->rxchannel->name);
+ tmpstr,tele,myrpt->rxchannel->name);
ast_call(myrpt->rxchannel,tele,999);
+ if (myrpt->rxchannel->_state != AST_STATE_UP)
+ {
+ ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
}
else
{
@@ -2719,7 +2810,8 @@ char cmd[MAXDTMF+1] = "";
}
if (myrpt->txchanname)
{
- tele = strchr(myrpt->txchanname,'/');
+ strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
+ tele = strchr(tmpstr,'/');
if (!tele)
{
fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname);
@@ -2727,9 +2819,17 @@ char cmd[MAXDTMF+1] = "";
pthread_exit(NULL);
}
*tele++ = 0;
- myrpt->txchannel = ast_request(myrpt->txchanname,AST_FORMAT_SLINEAR,tele);
+ myrpt->txchannel = ast_request(tmpstr,AST_FORMAT_SLINEAR,tele);
if (myrpt->txchannel)
{
+ if (myrpt->txchannel->_state == AST_STATE_BUSY)
+ {
+ fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
+ ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
+ pthread_exit(NULL);
+ }
ast_set_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
myrpt->txchannel->whentohangup = 0;
@@ -2737,13 +2837,21 @@ char cmd[MAXDTMF+1] = "";
myrpt->txchannel->data = "(Repeater Rx)";
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n",
- myrpt->txchanname,tele,myrpt->txchannel->name);
+ tmpstr,tele,myrpt->txchannel->name);
ast_call(myrpt->txchannel,tele,999);
+ if (myrpt->rxchannel->_state != AST_STATE_UP)
+ {
+ ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->rxchannel);
+ ast_hangup(myrpt->txchannel);
+ pthread_exit(NULL);
+ }
}
else
{
fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
}
@@ -2757,6 +2865,9 @@ char cmd[MAXDTMF+1] = "";
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_mutex_unlock(&myrpt->lock);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
/* make a conference for the tx */
@@ -2768,6 +2879,10 @@ char cmd[MAXDTMF+1] = "";
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
/* save tx conference number */
@@ -2781,6 +2896,10 @@ char cmd[MAXDTMF+1] = "";
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
/* save pseudo channel conference number */
@@ -2791,6 +2910,10 @@ char cmd[MAXDTMF+1] = "";
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
/* make a conference for the tx */
@@ -2802,6 +2925,11 @@ char cmd[MAXDTMF+1] = "";
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_mutex_unlock(&myrpt->lock);
+ ast_hangup(myrpt->txpchannel);
+ ast_hangup(myrpt->pchannel);
+ if (myrpt->txchannel != myrpt->rxchannel)
+ ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
pthread_exit(NULL);
}
/* Now, the idea here is to copy from the physical rx channel buffer
@@ -2843,6 +2971,9 @@ char cmd[MAXDTMF+1] = "";
if (ast_check_hangup(myrpt->txpchannel)) break;
ast_mutex_lock(&myrpt->lock);
myrpt->localtx = keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]);
+
+ /* If someone's connected, and they're transmitting from their end to us, set remrx true */
+
l = myrpt->links.next;
remrx = 0;
while(l != &myrpt->links)
@@ -2924,8 +3055,8 @@ char cmd[MAXDTMF+1] = "";
if (!myrpt->totimer) myrpt->tailtimer = 0;
/* if not timed-out, add in tail */
if (myrpt->totimer) totx = totx || myrpt->tailtimer;
- /* If user keys up or is keyed up over standard ID, switch to talkover ID, if one is defined */
- if (identqueued && keyed && idtalkover) {
+ /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
+ if (identqueued && (keyed || remrx) && idtalkover) {
int hasid = 0,hastalkover = 0;
telem = myrpt->tele.next;
@@ -3384,8 +3515,8 @@ char cmd[MAXDTMF+1] = "";
ast_mutex_lock(&myrpt->lock);
ast_hangup(myrpt->pchannel);
ast_hangup(myrpt->txpchannel);
- ast_hangup(myrpt->rxchannel);
if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
+ ast_hangup(myrpt->rxchannel);
l = myrpt->links.next;
while(l != &myrpt->links)
{
@@ -3411,6 +3542,7 @@ static void *rpt_master(void *ignore)
char *this,*val;
struct ast_variable *vp;
int i,j,n,longestnode;
+pthread_attr_t attr;
/* start with blank config */
memset(&rpt_vars,0,sizeof(rpt_vars));
@@ -3452,6 +3584,7 @@ int i,j,n,longestnode;
ast_mutex_init(&rpt_vars[n].lock);
rpt_vars[n].tele.next = &rpt_vars[n].tele;
rpt_vars[n].tele.prev = &rpt_vars[n].tele;
+ rpt_vars[n].rpt_thread = AST_PTHREADT_NULL;
rpt_vars[n].name = this;
rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
@@ -3469,7 +3602,6 @@ int i,j,n,longestnode;
rpt_vars[n].idtime = retrieve_astcfgint( this, "idtime", 60000, 2400000, IDTIME); /* Enforce a min max */
rpt_vars[n].politeid = retrieve_astcfgint( this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */
-
rpt_vars[n].remote = ast_variable_retrieve(cfg,this,"remote");
rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
val = ast_variable_retrieve(cfg,this,"iobase");
@@ -3543,8 +3675,24 @@ int i,j,n,longestnode;
}
ast_pthread_create(&rpt_vars[i].rpt_thread,NULL,rpt,(void *) &rpt_vars[i]);
}
- /* wait for first one to die (should be never) */
- pthread_join(rpt_vars[0].rpt_thread,NULL);
+ usleep(500000);
+ for(;;)
+ {
+ /* Now monitor each thread, and restart it if necessary */
+ for(i = 0; i < n; i++)
+ {
+ if (rpt_vars[i].remote) continue;
+ if (pthread_kill(rpt_vars[i].rpt_thread,0))
+ {
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ ast_pthread_create(&rpt_vars[i].rpt_thread,&attr,rpt,(void *) &rpt_vars[i]);
+ ast_log(LOG_WARNING, "rpt_thread restarted on node %s\n", rpt_vars[i].name);
+ }
+
+ }
+ usleep(2000000);
+ }
pthread_exit(NULL);
}