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: https://origsvn.digium.com/svn/asterisk/trunk@3631 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Jim Dixon
2004-08-21 21:41:54 +00:00
parent de3528f0be
commit d8436708c0
2 changed files with 209 additions and 41 deletions

View File

@@ -3,7 +3,7 @@
* Asterisk -- A telephony toolkit for Linux. * Asterisk -- A telephony toolkit for Linux.
* *
* Radio Repeater / Remote Base program * 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 * 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 {DC_INDETERMINATE, DC_REQ_FLUSH, DC_ERROR, DC_COMPLETE};
enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT}; enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT};
enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
#include <asterisk/utils.h> #include <asterisk/utils.h>
#include <asterisk/lock.h> #include <asterisk/lock.h>
#include <asterisk/file.h> #include <asterisk/file.h>
@@ -114,7 +116,6 @@ enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT};
#include <asterisk/translate.h> #include <asterisk/translate.h>
#include <asterisk/options.h> #include <asterisk/options.h>
#include <asterisk/config.h> #include <asterisk/config.h>
#include <asterisk/utils.h>
#include <asterisk/say.h> #include <asterisk/say.h>
#include <asterisk/localtime.h> #include <asterisk/localtime.h>
#include <stdio.h> #include <stdio.h>
@@ -136,7 +137,7 @@ enum {SOURCE_RPT, SOURCE_LNK, SOURCE_RMT};
#include <tonezone.h> #include <tonezone.h>
#include <linux/zaptel.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 *app = "Rpt";
static char *synopsis = "Radio Repeater/Remote Base Control System"; static char *synopsis = "Radio Repeater/Remote Base Control System";
@@ -160,6 +161,7 @@ LOCAL_USER_DECL;
#define IDTIME 300000 #define IDTIME 300000
#define MAXRPTS 20 #define MAXRPTS 20
#define POLITEID 30000 #define POLITEID 30000
#define FUNCTDELAY 1500
static pthread_t rpt_master_thread; 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. * 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 res;
int i; int i;
char *entry; char *entry;
char *telemetry;
char *telemetry_save;
res = 0; res = 0;
telemetry_save = NULL;
entry = 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 */ /* Try to look up the telemetry name */
entry = ast_variable_retrieve(cfg, TELEMETRY, name);
if(!entry){ if(!entry){
/* Telemetry name wasn't found in the config file, use the default */ /* Telemetry name wasn't found in the config file, use the default */
for(i = 0; i < sizeof(tele_defs)/sizeof(struct telem_defaults) ; i++){ 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; 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) static void *rpt_tele_thread(void *this)
{ {
ZT_CONFINFO ci; /* conference info */ ZT_CONFINFO ci; /* conference info */
@@ -713,8 +790,7 @@ struct tm localtm;
case ID: case ID:
case ID1: case ID1:
/* wait a bit */ /* wait a bit */
usleep(500000); wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM);
res = telem_any(mychannel, ident); res = telem_any(mychannel, ident);
imdone=1; imdone=1;
@@ -730,22 +806,22 @@ struct tm localtm;
case PROC: case PROC:
/* wait a little bit longer */ /* wait a little bit longer */
usleep(1500000); wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language); res = ast_streamfile(mychannel, "rpt/callproceeding", mychannel->language);
break; break;
case TERM: case TERM:
/* wait a little bit longer */ /* wait a little bit longer */
usleep(1500000); wait_interval(myrpt, DLY_CALLTERM);
res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language); res = ast_streamfile(mychannel, "rpt/callterminated", mychannel->language);
break; break;
case COMPLETE: case COMPLETE:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
res = telem_lookup(mychannel, "functcomplete"); res = telem_lookup(mychannel, myrpt->name, "functcomplete");
break; break;
case UNKEY: case UNKEY:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_UNKEY);
hastx = 0; hastx = 0;
@@ -760,7 +836,7 @@ struct tm localtm;
} }
ast_mutex_unlock(&myrpt->lock); ast_mutex_unlock(&myrpt->lock);
res = telem_lookup(mychannel,(!hastx) ? "remotemon" : "remotetx"); res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
if(res) if(res)
ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name); ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
@@ -769,7 +845,7 @@ struct tm localtm;
if (myrpt->cmdnode[0]) if (myrpt->cmdnode[0])
{ {
ast_safe_sleep(mychannel,200); ast_safe_sleep(mychannel,200);
res = telem_lookup(mychannel, "cmdmode"); res = telem_lookup(mychannel, myrpt->name, "cmdmode");
if(res) if(res)
ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name); ast_log(LOG_WARNING, "telem_lookup:cmdmode failed on %s\n", mychannel->name);
ast_stopstream(mychannel); ast_stopstream(mychannel);
@@ -777,7 +853,7 @@ struct tm localtm;
} }
else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */ else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
ct_copy = ast_strdupa(ct); ct_copy = ast_strdupa(ct);
res = telem_lookup(mychannel, ct_copy); res = telem_lookup(mychannel, myrpt->name, ct_copy);
if(res) if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name); ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
} }
@@ -786,7 +862,7 @@ struct tm localtm;
break; break;
case REMDISC: case REMDISC:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/node", mychannel->language); res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res) if (!res)
res = ast_waitstream(mychannel, ""); res = ast_waitstream(mychannel, "");
@@ -799,22 +875,22 @@ struct tm localtm;
break; break;
case REMALREADY: case REMALREADY:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language); res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
break; break;
case REMNOTFOUND: case REMNOTFOUND:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language); res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
break; break;
case REMGO: case REMGO:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language); res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
break; break;
case CONNECTED: case CONNECTED:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
res = ast_streamfile(mychannel, "rpt/node", mychannel->language); res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res) if (!res)
res = ast_waitstream(mychannel, ""); res = ast_waitstream(mychannel, "");
@@ -836,7 +912,7 @@ struct tm localtm;
break; break;
case STATUS: case STATUS:
/* wait a little bit */ /* wait a little bit */
usleep(1000000); wait_interval(myrpt, DLY_TELEM);
hastx = 0; hastx = 0;
linkbase.next = &linkbase; linkbase.next = &linkbase;
linkbase.prev = &linkbase; linkbase.prev = &linkbase;
@@ -936,7 +1012,7 @@ struct tm localtm;
break; break;
case STATS_TIME: case STATS_TIME:
usleep(1000000); /* Wait a little bit */ wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
t = time(NULL); t = time(NULL);
ast_localtime(&t, &localtm, NULL); ast_localtime(&t, &localtm, NULL);
/* Say the phase of the day is before the time */ /* Say the phase of the day is before the time */
@@ -970,7 +1046,7 @@ struct tm localtm;
break; break;
if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2) if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
break; break;
usleep(1000000); /* Wait a little bit */ wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
/* Say "version" */ /* Say "version" */
if (sayfile(mychannel,"rpt/version") == -1) if (sayfile(mychannel,"rpt/version") == -1)
{ {
@@ -998,7 +1074,7 @@ struct tm localtm;
imdone = 1; imdone = 1;
break; break;
case ARB_ALPHA: case ARB_ALPHA:
usleep(1000000); /* Wait a little bit */ wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
if(mytele->param) if(mytele->param)
saycharstr(mychannel, mytele->param); saycharstr(mychannel, mytele->param);
imdone = 1; imdone = 1;
@@ -2666,7 +2742,7 @@ int seq,res;
ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY); ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_KEY);
} }
if (ast_safe_sleep(myrpt->remchannel,1000) == -1) return -1; 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) if (!myrpt->remoterx)
{ {
ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY); ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
@@ -2686,11 +2762,13 @@ time_t dtmf_time,t;
struct rpt_link *l,*m; struct rpt_link *l,*m;
struct rpt_tele *telem; struct rpt_tele *telem;
pthread_attr_t attr; pthread_attr_t attr;
char tmpstr[300];
char cmd[MAXDTMF+1] = ""; char cmd[MAXDTMF+1] = "";
ast_mutex_lock(&myrpt->lock); ast_mutex_lock(&myrpt->lock);
tele = strchr(myrpt->rxchanname,'/'); strncpy(tmpstr,myrpt->rxchanname,sizeof(tmpstr) - 1);
tele = strchr(tmpstr,'/');
if (!tele) if (!tele)
{ {
fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->rxchanname); 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); pthread_exit(NULL);
} }
*tele++ = 0; *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)
{ {
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_read_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR); ast_set_write_format(myrpt->rxchannel,AST_FORMAT_SLINEAR);
myrpt->rxchannel->whentohangup = 0; myrpt->rxchannel->whentohangup = 0;
@@ -2708,8 +2793,14 @@ char cmd[MAXDTMF+1] = "";
myrpt->rxchannel->data = "(Repeater Rx)"; myrpt->rxchannel->data = "(Repeater Rx)";
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (Rx) initiating call to %s/%s on %s\n", 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); 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 else
{ {
@@ -2719,7 +2810,8 @@ char cmd[MAXDTMF+1] = "";
} }
if (myrpt->txchanname) if (myrpt->txchanname)
{ {
tele = strchr(myrpt->txchanname,'/'); strncpy(tmpstr,myrpt->txchanname,sizeof(tmpstr) - 1);
tele = strchr(tmpstr,'/');
if (!tele) if (!tele)
{ {
fprintf(stderr,"rpt:Dial number (%s) must be in format tech/number\n",myrpt->txchanname); 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); pthread_exit(NULL);
} }
*tele++ = 0; *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)
{ {
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_read_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR); ast_set_write_format(myrpt->txchannel,AST_FORMAT_SLINEAR);
myrpt->txchannel->whentohangup = 0; myrpt->txchannel->whentohangup = 0;
@@ -2737,13 +2837,21 @@ char cmd[MAXDTMF+1] = "";
myrpt->txchannel->data = "(Repeater Rx)"; myrpt->txchannel->data = "(Repeater Rx)";
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "rpt (Tx) initiating call to %s/%s on %s\n", 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); 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 else
{ {
fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n"); fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
ast_mutex_unlock(&myrpt->lock); ast_mutex_unlock(&myrpt->lock);
ast_hangup(myrpt->rxchannel);
pthread_exit(NULL); pthread_exit(NULL);
} }
} }
@@ -2757,6 +2865,9 @@ char cmd[MAXDTMF+1] = "";
{ {
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_mutex_unlock(&myrpt->lock); ast_mutex_unlock(&myrpt->lock);
if (myrpt->txchannel != myrpt->rxchannel)
ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
pthread_exit(NULL); pthread_exit(NULL);
} }
/* make a conference for the tx */ /* 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_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_mutex_unlock(&myrpt->lock); 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); pthread_exit(NULL);
} }
/* save tx conference number */ /* 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_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_mutex_unlock(&myrpt->lock); 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); pthread_exit(NULL);
} }
/* save pseudo channel conference number */ /* save pseudo channel conference number */
@@ -2791,6 +2910,10 @@ char cmd[MAXDTMF+1] = "";
{ {
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n"); fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_mutex_unlock(&myrpt->lock); 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); pthread_exit(NULL);
} }
/* make a conference for the tx */ /* 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_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_mutex_unlock(&myrpt->lock); 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); pthread_exit(NULL);
} }
/* Now, the idea here is to copy from the physical rx channel buffer /* 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; if (ast_check_hangup(myrpt->txpchannel)) break;
ast_mutex_lock(&myrpt->lock); ast_mutex_lock(&myrpt->lock);
myrpt->localtx = keyed && (myrpt->dtmfidx == -1) && (!myrpt->cmdnode[0]); 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; l = myrpt->links.next;
remrx = 0; remrx = 0;
while(l != &myrpt->links) while(l != &myrpt->links)
@@ -2924,8 +3055,8 @@ char cmd[MAXDTMF+1] = "";
if (!myrpt->totimer) myrpt->tailtimer = 0; if (!myrpt->totimer) myrpt->tailtimer = 0;
/* if not timed-out, add in tail */ /* if not timed-out, add in tail */
if (myrpt->totimer) totx = totx || myrpt->tailtimer; 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 user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */
if (identqueued && keyed && idtalkover) { if (identqueued && (keyed || remrx) && idtalkover) {
int hasid = 0,hastalkover = 0; int hasid = 0,hastalkover = 0;
telem = myrpt->tele.next; telem = myrpt->tele.next;
@@ -3384,8 +3515,8 @@ char cmd[MAXDTMF+1] = "";
ast_mutex_lock(&myrpt->lock); ast_mutex_lock(&myrpt->lock);
ast_hangup(myrpt->pchannel); ast_hangup(myrpt->pchannel);
ast_hangup(myrpt->txpchannel); ast_hangup(myrpt->txpchannel);
ast_hangup(myrpt->rxchannel);
if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel); if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
ast_hangup(myrpt->rxchannel);
l = myrpt->links.next; l = myrpt->links.next;
while(l != &myrpt->links) while(l != &myrpt->links)
{ {
@@ -3411,6 +3542,7 @@ static void *rpt_master(void *ignore)
char *this,*val; char *this,*val;
struct ast_variable *vp; struct ast_variable *vp;
int i,j,n,longestnode; int i,j,n,longestnode;
pthread_attr_t attr;
/* start with blank config */ /* start with blank config */
memset(&rpt_vars,0,sizeof(rpt_vars)); memset(&rpt_vars,0,sizeof(rpt_vars));
@@ -3452,6 +3584,7 @@ int i,j,n,longestnode;
ast_mutex_init(&rpt_vars[n].lock); ast_mutex_init(&rpt_vars[n].lock);
rpt_vars[n].tele.next = &rpt_vars[n].tele; rpt_vars[n].tele.next = &rpt_vars[n].tele;
rpt_vars[n].tele.prev = &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].name = this;
rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel"); rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel"); 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].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].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].remote = ast_variable_retrieve(cfg,this,"remote");
rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone"); rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
val = ast_variable_retrieve(cfg,this,"iobase"); 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]); ast_pthread_create(&rpt_vars[i].rpt_thread,NULL,rpt,(void *) &rpt_vars[i]);
} }
/* wait for first one to die (should be never) */ usleep(500000);
pthread_join(rpt_vars[0].rpt_thread,NULL); 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); pthread_exit(NULL);
} }

View File

@@ -2114,7 +2114,7 @@ static int zt_hangup(struct ast_channel *ast)
ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook); ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
#endif #endif
/* If they're off hook, try playing congestion */ /* If they're off hook, try playing congestion */
if (par.rxisoffhook) if ((par.rxisoffhook) && (!p->radio))
tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION); tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
else else
tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1); tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
@@ -3728,6 +3728,8 @@ struct ast_frame *zt_read(struct ast_channel *ast)
return NULL; return NULL;
} }
if (p->radio && p->inalarm) return NULL;
p->subs[index].f.frametype = AST_FRAME_NULL; p->subs[index].f.frametype = AST_FRAME_NULL;
p->subs[index].f.datalen = 0; p->subs[index].f.datalen = 0;
p->subs[index].f.samples = 0; p->subs[index].f.samples = 0;
@@ -5217,11 +5219,11 @@ static int handle_init_event(struct zt_pvt *i, int event)
struct ast_channel *chan; struct ast_channel *chan;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
if (i->radio) return 0;
/* Handle an event on a given channel for the monitor thread. */ /* Handle an event on a given channel for the monitor thread. */
switch(event) { switch(event) {
case ZT_EVENT_NONE: case ZT_EVENT_NONE:
case ZT_EVENT_BITSCHANGED: case ZT_EVENT_BITSCHANGED:
if (i->radio) break;
#ifdef ZAPATA_R2 #ifdef ZAPATA_R2
if (i->r2) { if (i->r2) {
mfcr2_event_t *e; mfcr2_event_t *e;
@@ -5235,6 +5237,7 @@ static int handle_init_event(struct zt_pvt *i, int event)
case ZT_EVENT_WINKFLASH: case ZT_EVENT_WINKFLASH:
case ZT_EVENT_RINGOFFHOOK: case ZT_EVENT_RINGOFFHOOK:
if (i->inalarm) break; if (i->inalarm) break;
if (i->radio) break;
/* Got a ring/answer. What kind of channel are we? */ /* Got a ring/answer. What kind of channel are we? */
switch(i->sig) { switch(i->sig) {
case SIG_FXOLS: case SIG_FXOLS:
@@ -5331,6 +5334,7 @@ static int handle_init_event(struct zt_pvt *i, int event)
ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res)); ast_log(LOG_WARNING, "Detected alarm on channel %d: %s\n", i->channel, alarm2str(res));
/* fall thru intentionally */ /* fall thru intentionally */
case ZT_EVENT_ONHOOK: case ZT_EVENT_ONHOOK:
if (i->radio) break;
/* Back on hook. Hang up. */ /* Back on hook. Hang up. */
switch(i->sig) { switch(i->sig) {
case SIG_FXOLS: case SIG_FXOLS:
@@ -5506,7 +5510,22 @@ static void *do_monitor(void *data)
} }
} }
} }
if ((i->subs[SUB_REAL].zfd > -1) && i->sig && (!i->radio)) { if ((i->subs[SUB_REAL].zfd > -1) && i->sig) {
if (i->radio && !i->owner)
{
res = zt_get_event(i->subs[SUB_REAL].zfd);
if (res)
{
if (option_debug)
ast_log(LOG_DEBUG, "Monitor doohicky got event %s on radio channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events */
ast_mutex_unlock(&iflock);
handle_init_event(i, res);
ast_mutex_lock(&iflock);
}
i = i->next;
continue;
}
pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint); pollres = ast_fdisset(pfds, i->subs[SUB_REAL].zfd, count, &spoint);
if (pollres & POLLIN) { if (pollres & POLLIN) {
if (i->owner || i->subs[SUB_REAL].owner) { if (i->owner || i->subs[SUB_REAL].owner) {
@@ -6489,7 +6508,7 @@ static struct ast_channel *zt_request(char *type, int format, void *data)
if (p && available(p, channelmatch, groupmatch, &busy)) { if (p && available(p, channelmatch, groupmatch, &busy)) {
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Using channel %d\n", p->channel); ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
if (p->inalarm) if (p->inalarm)
goto next; goto next;
callwait = (p->owner != NULL); callwait = (p->owner != NULL);
@@ -8147,6 +8166,7 @@ static int zap_show_channel(int fd, int argc, char **argv)
ast_cli(fd, "Context: %s\n", tmp->context); ast_cli(fd, "Context: %s\n", tmp->context);
ast_cli(fd, "Caller ID string: %s\n", tmp->callerid); ast_cli(fd, "Caller ID string: %s\n", tmp->callerid);
ast_cli(fd, "Destroy: %d\n", tmp->destroy); ast_cli(fd, "Destroy: %d\n", tmp->destroy);
ast_cli(fd, "InAlarm: %d\n", tmp->inalarm);
ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig)); ast_cli(fd, "Signalling Type: %s\n", sig2str(tmp->sig));
ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>"); ast_cli(fd, "Owner: %s\n", tmp->owner ? tmp->owner->name : "<None>");
ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : ""); ast_cli(fd, "Real: %s%s%s\n", tmp->subs[SUB_REAL].owner ? tmp->subs[SUB_REAL].owner->name : "<None>", tmp->subs[SUB_REAL].inthreeway ? " (Confed)" : "", tmp->subs[SUB_REAL].linear ? " (Linear)" : "");