mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-13 08:13:22 +00:00
Fixed some bugs; added re-connect mode
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@4794 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
293
apps/app_rpt.c
293
apps/app_rpt.c
@@ -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.18 11/16/04
|
* version 0.19 01/14/05
|
||||||
*
|
*
|
||||||
* See http://www.zapatatelephony.org/app_rpt.html
|
* See http://www.zapatatelephony.org/app_rpt.html
|
||||||
*
|
*
|
||||||
@@ -63,11 +63,24 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* The following is JUST GROSS!! There is some soft of underlying problem,
|
||||||
|
probably in channel_iax2.c, that causes an IAX2 connection to sometimes
|
||||||
|
stop transmitting randomly. We have been working for weeks to try to
|
||||||
|
locate it and fix it, but to no avail We finally decided to put our
|
||||||
|
tail between our legs, and just make the radio system re-connect upon
|
||||||
|
network failure. This just shouldnt have to be done. For normal operation,
|
||||||
|
comment-out the following line */
|
||||||
|
#define RECONNECT_KLUDGE
|
||||||
|
|
||||||
/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
|
/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
|
||||||
|
|
||||||
#define MAXDTMF 32
|
#define MAXDTMF 32
|
||||||
#define DTMF_TIMEOUT 3
|
#define DTMF_TIMEOUT 3
|
||||||
|
|
||||||
|
#define DISC_TIME 10000 /* report disc after 10 seconds of no connect */
|
||||||
|
#define MAX_RETRIES 5
|
||||||
|
|
||||||
|
#define RETRY_TIMER_MS 5000
|
||||||
|
|
||||||
#define MAXREMSTR 15
|
#define MAXREMSTR 15
|
||||||
|
|
||||||
@@ -137,7 +150,7 @@ enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM};
|
|||||||
#include <tonezone.h>
|
#include <tonezone.h>
|
||||||
#include <linux/zaptel.h>
|
#include <linux/zaptel.h>
|
||||||
|
|
||||||
static char *tdesc = "Radio Repeater / Remote Base version 0.18 11/16/2004";
|
static char *tdesc = "Radio Repeater / Remote Base version 0.19 01/14/2005";
|
||||||
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";
|
||||||
@@ -148,7 +161,7 @@ static char *descrip =
|
|||||||
static int debug = 0; /* Set this >0 for extra debug output */
|
static int debug = 0; /* Set this >0 for extra debug output */
|
||||||
static int nrpts = 0;
|
static int nrpts = 0;
|
||||||
|
|
||||||
|
char *discstr = "!!DISCONNECT!!";
|
||||||
|
|
||||||
struct ast_config *cfg;
|
struct ast_config *cfg;
|
||||||
|
|
||||||
@@ -178,7 +191,11 @@ struct rpt_link
|
|||||||
char lastrx;
|
char lastrx;
|
||||||
char connected;
|
char connected;
|
||||||
char outbound;
|
char outbound;
|
||||||
|
char disced;
|
||||||
long elaptime;
|
long elaptime;
|
||||||
|
long disctime;
|
||||||
|
long retrytimer;
|
||||||
|
int retries;
|
||||||
struct ast_channel *chan;
|
struct ast_channel *chan;
|
||||||
struct ast_channel *pchan;
|
struct ast_channel *pchan;
|
||||||
} ;
|
} ;
|
||||||
@@ -689,7 +706,7 @@ static int telem_lookup(struct ast_channel *chan, char *node, char *name)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
static void wait_interval(struct rpt *myrpt, int type)
|
static void wait_interval(struct rpt *myrpt, int type, struct ast_channel *chan)
|
||||||
{
|
{
|
||||||
int interval;
|
int interval;
|
||||||
char *wait_times;
|
char *wait_times;
|
||||||
@@ -739,7 +756,7 @@ static void wait_interval(struct rpt *myrpt, int type)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
usleep(1000 * interval);
|
ast_safe_sleep(chan,interval);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -808,7 +825,7 @@ struct tm localtm;
|
|||||||
case ID:
|
case ID:
|
||||||
case ID1:
|
case ID1:
|
||||||
/* wait a bit */
|
/* wait a bit */
|
||||||
wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM);
|
wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel);
|
||||||
res = telem_any(mychannel, ident);
|
res = telem_any(mychannel, ident);
|
||||||
imdone=1;
|
imdone=1;
|
||||||
|
|
||||||
@@ -824,17 +841,17 @@ struct tm localtm;
|
|||||||
|
|
||||||
case PROC:
|
case PROC:
|
||||||
/* wait a little bit longer */
|
/* wait a little bit longer */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
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 */
|
||||||
wait_interval(myrpt, DLY_CALLTERM);
|
wait_interval(myrpt, DLY_CALLTERM, mychannel);
|
||||||
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 */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
res = telem_lookup(mychannel, myrpt->name, "functcomplete");
|
res = telem_lookup(mychannel, myrpt->name, "functcomplete");
|
||||||
break;
|
break;
|
||||||
case UNKEY:
|
case UNKEY:
|
||||||
@@ -860,7 +877,7 @@ struct tm localtm;
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* wait a little bit */
|
/* wait a little bit */
|
||||||
wait_interval(myrpt, DLY_UNKEY);
|
wait_interval(myrpt, DLY_UNKEY, mychannel);
|
||||||
hastx = 0;
|
hastx = 0;
|
||||||
|
|
||||||
|
|
||||||
@@ -901,7 +918,7 @@ struct tm localtm;
|
|||||||
break;
|
break;
|
||||||
case REMDISC:
|
case REMDISC:
|
||||||
/* wait a little bit */
|
/* wait a little bit */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
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, "");
|
||||||
@@ -914,22 +931,22 @@ struct tm localtm;
|
|||||||
break;
|
break;
|
||||||
case REMALREADY:
|
case REMALREADY:
|
||||||
/* wait a little bit */
|
/* wait a little bit */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
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 */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
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 */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
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 */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
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, "");
|
||||||
@@ -951,7 +968,7 @@ struct tm localtm;
|
|||||||
break;
|
break;
|
||||||
case STATUS:
|
case STATUS:
|
||||||
/* wait a little bit */
|
/* wait a little bit */
|
||||||
wait_interval(myrpt, DLY_TELEM);
|
wait_interval(myrpt, DLY_TELEM, mychannel);
|
||||||
hastx = 0;
|
hastx = 0;
|
||||||
linkbase.next = &linkbase;
|
linkbase.next = &linkbase;
|
||||||
linkbase.prev = &linkbase;
|
linkbase.prev = &linkbase;
|
||||||
@@ -1051,7 +1068,7 @@ struct tm localtm;
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STATS_TIME:
|
case STATS_TIME:
|
||||||
wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
|
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
|
||||||
t = time(NULL);
|
t = time(NULL);
|
||||||
localtime_r(&t, &localtm);
|
localtime_r(&t, &localtm);
|
||||||
/* Say the phase of the day is before the time */
|
/* Say the phase of the day is before the time */
|
||||||
@@ -1085,7 +1102,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;
|
||||||
wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
|
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
|
||||||
/* Say "version" */
|
/* Say "version" */
|
||||||
if (sayfile(mychannel,"rpt/version") == -1)
|
if (sayfile(mychannel,"rpt/version") == -1)
|
||||||
{
|
{
|
||||||
@@ -1113,7 +1130,7 @@ struct tm localtm;
|
|||||||
imdone = 1;
|
imdone = 1;
|
||||||
break;
|
break;
|
||||||
case ARB_ALPHA:
|
case ARB_ALPHA:
|
||||||
wait_interval(myrpt, DLY_TELEM); /* Wait a little bit */
|
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
|
||||||
if(mytele->param)
|
if(mytele->param)
|
||||||
saycharstr(mychannel, mytele->param);
|
saycharstr(mychannel, mytele->param);
|
||||||
imdone = 1;
|
imdone = 1;
|
||||||
@@ -1376,7 +1393,11 @@ struct ast_channel *mychannel,*genchannel;
|
|||||||
myrpt->mydtmf = 0;
|
myrpt->mydtmf = 0;
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
usleep(25000);
|
if (ast_safe_sleep(mychannel,25))
|
||||||
|
{
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
ast_mutex_lock(&myrpt->lock);
|
ast_mutex_lock(&myrpt->lock);
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
@@ -1410,7 +1431,7 @@ struct rpt_link *l;
|
|||||||
if (!strcmp(l->name,myrpt->cmdnode))
|
if (!strcmp(l->name,myrpt->cmdnode))
|
||||||
{
|
{
|
||||||
wf.data = strdup(str);
|
wf.data = strdup(str);
|
||||||
ast_write(l->chan,&wf);
|
if (l->chan) ast_write(l->chan,&wf);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
l = l->next;
|
l = l->next;
|
||||||
@@ -1420,7 +1441,7 @@ struct rpt_link *l;
|
|||||||
while(l != &myrpt->links)
|
while(l != &myrpt->links)
|
||||||
{
|
{
|
||||||
wf.data = strdup(str);
|
wf.data = strdup(str);
|
||||||
ast_write(l->chan,&wf);
|
if (l->chan) ast_write(l->chan,&wf);
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1450,8 +1471,6 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
|
|
||||||
switch(myatoi(param)){
|
switch(myatoi(param)){
|
||||||
case 1: /* Link off */
|
case 1: /* Link off */
|
||||||
|
|
||||||
|
|
||||||
val = ast_variable_retrieve(cfg, NODES, digitbuf);
|
val = ast_variable_retrieve(cfg, NODES, digitbuf);
|
||||||
if (!val){
|
if (!val){
|
||||||
if(strlen(digitbuf) >= myrpt->longestnode)
|
if(strlen(digitbuf) >= myrpt->longestnode)
|
||||||
@@ -1471,8 +1490,24 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
if (l != &myrpt->links){ /* if found */
|
if (l != &myrpt->links){ /* if found */
|
||||||
|
struct ast_frame wf;
|
||||||
|
|
||||||
|
l->retries = MAX_RETRIES + 1;
|
||||||
|
l->disced = 1;
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
wf.frametype = AST_FRAME_TEXT;
|
||||||
|
wf.subclass = 0;
|
||||||
|
wf.offset = 0;
|
||||||
|
wf.mallocd = 1;
|
||||||
|
wf.datalen = strlen(discstr) + 1;
|
||||||
|
wf.samples = 0;
|
||||||
|
wf.data = strdup(discstr);
|
||||||
|
if (l->chan)
|
||||||
|
{
|
||||||
|
ast_write(l->chan,&wf);
|
||||||
|
if (ast_safe_sleep(l->chan,250) == -1) return DC_ERROR;
|
||||||
ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
||||||
|
}
|
||||||
rpt_telemetry(myrpt, COMPLETE, NULL);
|
rpt_telemetry(myrpt, COMPLETE, NULL);
|
||||||
return DC_COMPLETE;
|
return DC_COMPLETE;
|
||||||
}
|
}
|
||||||
@@ -1501,13 +1536,13 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
if (l != &myrpt->links)
|
if (l != &myrpt->links)
|
||||||
{
|
{
|
||||||
/* if already in this mode, just ignore */
|
/* if already in this mode, just ignore */
|
||||||
if (!l->mode) {
|
if ((!l->mode) || (!l->chan)) {
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
rpt_telemetry(myrpt,REMALREADY,NULL);
|
rpt_telemetry(myrpt,REMALREADY,NULL);
|
||||||
return DC_COMPLETE;
|
return DC_COMPLETE;
|
||||||
|
|
||||||
}
|
}
|
||||||
ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
/* establish call in monitor mode */
|
/* establish call in monitor mode */
|
||||||
@@ -1544,6 +1579,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
rpt_telemetry(myrpt,CONNFAIL,l);
|
||||||
free(l);
|
free(l);
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
|
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
|
||||||
@@ -1596,12 +1632,12 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
/* if found */
|
/* if found */
|
||||||
if (l != &myrpt->links){
|
if (l != &myrpt->links){
|
||||||
/* if already in this mode, just ignore */
|
/* if already in this mode, just ignore */
|
||||||
if (l->mode){
|
if ((l->mode) || (!l->chan)) {
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
rpt_telemetry(myrpt, REMALREADY, NULL);
|
rpt_telemetry(myrpt, REMALREADY, NULL);
|
||||||
return DC_COMPLETE;
|
return DC_COMPLETE;
|
||||||
}
|
}
|
||||||
ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
|
if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
/* establish call in tranceive mode */
|
/* establish call in tranceive mode */
|
||||||
@@ -1613,6 +1649,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
/* zero the silly thing */
|
/* zero the silly thing */
|
||||||
memset((char *)l,0,sizeof(struct rpt_link));
|
memset((char *)l,0,sizeof(struct rpt_link));
|
||||||
l->mode = 1;
|
l->mode = 1;
|
||||||
|
l->outbound = 1;
|
||||||
strncpy(l->name, digitbuf, MAXNODESTR - 1);
|
strncpy(l->name, digitbuf, MAXNODESTR - 1);
|
||||||
l->isremote = (s && ast_true(s));
|
l->isremote = (s && ast_true(s));
|
||||||
snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
|
snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
|
||||||
@@ -1638,6 +1675,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
ast_call(l->chan,tele,999);
|
ast_call(l->chan,tele,999);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
|
rpt_telemetry(myrpt,CONNFAIL,l);
|
||||||
free(l);
|
free(l);
|
||||||
if (option_verbose > 2)
|
if (option_verbose > 2)
|
||||||
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
|
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
|
||||||
@@ -1703,7 +1741,7 @@ static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int co
|
|||||||
l = myrpt->links.next;
|
l = myrpt->links.next;
|
||||||
|
|
||||||
while(l != &myrpt->links){
|
while(l != &myrpt->links){
|
||||||
ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
|
if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
rpt_telemetry(myrpt, COMPLETE, NULL);
|
rpt_telemetry(myrpt, COMPLETE, NULL);
|
||||||
@@ -2282,6 +2320,13 @@ struct ast_frame wf;
|
|||||||
wf.samples = 0;
|
wf.samples = 0;
|
||||||
/* put string in our buffer */
|
/* put string in our buffer */
|
||||||
strncpy(tmp,str,sizeof(tmp) - 1);
|
strncpy(tmp,str,sizeof(tmp) - 1);
|
||||||
|
if (!strcmp(tmp,discstr))
|
||||||
|
{
|
||||||
|
mylink->disced = 1;
|
||||||
|
mylink->retries = MAX_RETRIES + 1;
|
||||||
|
ast_softhangup(mylink->chan,AST_SOFTHANGUP_DEV);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
|
if (sscanf(tmp,"%s %s %s %d %c",cmd,dest,src,&seq,&c) != 5)
|
||||||
{
|
{
|
||||||
ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
|
ast_log(LOG_WARNING, "Unable to parse link string %s\n",str);
|
||||||
@@ -2311,7 +2356,7 @@ struct ast_frame wf;
|
|||||||
/* send, but not to src */
|
/* send, but not to src */
|
||||||
if (strcmp(l->name,src)) {
|
if (strcmp(l->name,src)) {
|
||||||
wf.data = strdup(str);
|
wf.data = strdup(str);
|
||||||
ast_write(l->chan,&wf);
|
if (l->chan) ast_write(l->chan,&wf);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2330,7 +2375,7 @@ struct ast_frame wf;
|
|||||||
/* send, but not to src */
|
/* send, but not to src */
|
||||||
if (strcmp(l->name,src)) {
|
if (strcmp(l->name,src)) {
|
||||||
wf.data = strdup(str);
|
wf.data = strdup(str);
|
||||||
ast_write(l->chan,&wf);
|
if (l->chan) ast_write(l->chan,&wf);
|
||||||
}
|
}
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
@@ -2830,6 +2875,57 @@ int seq,res;
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int attempt_reconnect(struct rpt *myrpt, struct rpt_link *l)
|
||||||
|
{
|
||||||
|
char *val, *s, *s1, *tele;
|
||||||
|
char tmp[300], deststr[300] = "";
|
||||||
|
|
||||||
|
val = ast_variable_retrieve(cfg, NODES, l->name);
|
||||||
|
if (!val)
|
||||||
|
{
|
||||||
|
fprintf(stderr,"attempt_reconnect: cannot find node %s\n",l->name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
strncpy(tmp,val,sizeof(tmp) - 1);
|
||||||
|
s = tmp;
|
||||||
|
s1 = strsep(&s,",");
|
||||||
|
ast_mutex_lock(&myrpt->lock);
|
||||||
|
snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
|
||||||
|
tele = strchr(deststr, '/');
|
||||||
|
if (!tele) {
|
||||||
|
fprintf(stderr,"attempt_reconnect:Dial number (%s) must be in format tech/number\n",deststr);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*tele++ = 0;
|
||||||
|
l->elaptime = 0;
|
||||||
|
l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele,NULL);
|
||||||
|
if (l->chan){
|
||||||
|
ast_set_read_format(l->chan, AST_FORMAT_SLINEAR);
|
||||||
|
ast_set_write_format(l->chan, AST_FORMAT_SLINEAR);
|
||||||
|
l->chan->whentohangup = 0;
|
||||||
|
l->chan->appl = "Apprpt";
|
||||||
|
l->chan->data = "(Remote Rx)";
|
||||||
|
if (option_verbose > 2)
|
||||||
|
ast_verbose(VERBOSE_PREFIX_3 "rpt (attempt_reconnect) initiating call to %s/%s on %s\n",
|
||||||
|
deststr, tele, l->chan->name);
|
||||||
|
if(l->chan->cid.cid_num)
|
||||||
|
free(l->chan->cid.cid_num);
|
||||||
|
l->chan->cid.cid_num = strdup(myrpt->name);
|
||||||
|
ast_call(l->chan,tele,999);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (option_verbose > 2)
|
||||||
|
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
|
||||||
|
deststr,tele,l->chan->name);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* single thread with one file (request) to dial */
|
/* single thread with one file (request) to dial */
|
||||||
static void *rpt(void *this)
|
static void *rpt(void *this)
|
||||||
{
|
{
|
||||||
@@ -3216,9 +3312,12 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
|
if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
|
||||||
l = myrpt->links.next;
|
l = myrpt->links.next;
|
||||||
while(l != &myrpt->links)
|
while(l != &myrpt->links)
|
||||||
|
{
|
||||||
|
if ((!l->disctime) && l->chan)
|
||||||
{
|
{
|
||||||
cs[n++] = l->chan;
|
cs[n++] = l->chan;
|
||||||
cs[n++] = l->pchan;
|
cs[n++] = l->pchan;
|
||||||
|
}
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
@@ -3230,6 +3329,23 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
l = myrpt->links.next;
|
l = myrpt->links.next;
|
||||||
while(l != &myrpt->links)
|
while(l != &myrpt->links)
|
||||||
{
|
{
|
||||||
|
#ifdef RECONNECT_KLUDGE
|
||||||
|
if (l->disctime && l->chan)
|
||||||
|
{
|
||||||
|
l->disctime -= elap;
|
||||||
|
if (l->disctime <= 0)
|
||||||
|
{
|
||||||
|
l->disctime = 0;
|
||||||
|
l->disced = 1;
|
||||||
|
ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l->retrytimer)
|
||||||
|
{
|
||||||
|
l->retrytimer -= elap;
|
||||||
|
if (l->retrytimer < 0) l->retrytimer = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* ignore non-timing channels */
|
/* ignore non-timing channels */
|
||||||
if (l->elaptime < 0)
|
if (l->elaptime < 0)
|
||||||
{
|
{
|
||||||
@@ -3239,13 +3355,57 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
l->elaptime += elap;
|
l->elaptime += elap;
|
||||||
/* if connection has taken too long */
|
/* if connection has taken too long */
|
||||||
if ((l->elaptime > MAXCONNECTTIME) &&
|
if ((l->elaptime > MAXCONNECTTIME) &&
|
||||||
(l->chan->_state != AST_STATE_UP))
|
((!l->chan) || (l->chan->_state != AST_STATE_UP)))
|
||||||
{
|
{
|
||||||
|
l->elaptime = 0;
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
||||||
|
#ifndef RECONNECT_KLUDGE
|
||||||
rpt_telemetry(myrpt,CONNFAIL,l);
|
rpt_telemetry(myrpt,CONNFAIL,l);
|
||||||
|
#endif
|
||||||
|
ast_mutex_lock(&myrpt->lock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifdef RECONNECT_KLUDGE
|
||||||
|
if ((!l->chan) && (!l->retrytimer) && l->outbound &&
|
||||||
|
(l->retries++ < MAX_RETRIES))
|
||||||
|
{
|
||||||
|
if (l->chan) ast_hangup(l->chan);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
if (attempt_reconnect(myrpt,l) == -1)
|
||||||
|
{
|
||||||
|
l->retrytimer = RETRY_TIMER_MS;
|
||||||
|
}
|
||||||
ast_mutex_lock(&myrpt->lock);
|
ast_mutex_lock(&myrpt->lock);
|
||||||
}
|
}
|
||||||
|
if ((!l->chan) && (!l->retrytimer) && l->outbound &&
|
||||||
|
(l->retries >= MAX_RETRIES))
|
||||||
|
{
|
||||||
|
/* remove from queue */
|
||||||
|
remque((struct qelem *) l);
|
||||||
|
if (!strcmp(myrpt->cmdnode,l->name))
|
||||||
|
myrpt->cmdnode[0] = 0;
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
rpt_telemetry(myrpt,REMDISC,l);
|
||||||
|
/* hang-up on call to device */
|
||||||
|
ast_hangup(l->pchan);
|
||||||
|
free(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((!l->chan) && (!l->disctime) && (!l->outbound))
|
||||||
|
{
|
||||||
|
/* remove from queue */
|
||||||
|
remque((struct qelem *) l);
|
||||||
|
if (!strcmp(myrpt->cmdnode,l->name))
|
||||||
|
myrpt->cmdnode[0] = 0;
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
rpt_telemetry(myrpt,REMDISC,l);
|
||||||
|
/* hang-up on call to device */
|
||||||
|
ast_hangup(l->pchan);
|
||||||
|
free(l);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
l = l->next;
|
l = l->next;
|
||||||
}
|
}
|
||||||
if (myrpt->tailtimer) myrpt->tailtimer -= elap;
|
if (myrpt->tailtimer) myrpt->tailtimer -= elap;
|
||||||
@@ -3464,6 +3624,11 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
l = myrpt->links.next;
|
l = myrpt->links.next;
|
||||||
while(l != &myrpt->links)
|
while(l != &myrpt->links)
|
||||||
{
|
{
|
||||||
|
if (l->disctime)
|
||||||
|
{
|
||||||
|
l = l->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (who == l->chan) /* if it was a read from rx */
|
if (who == l->chan) /* if it was a read from rx */
|
||||||
{
|
{
|
||||||
ast_mutex_lock(&myrpt->lock);
|
ast_mutex_lock(&myrpt->lock);
|
||||||
@@ -3494,6 +3659,30 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
f = ast_read(l->chan);
|
f = ast_read(l->chan);
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
|
#ifdef RECONNECT_KLUDGE
|
||||||
|
if ((!l->disced) && (!l->outbound))
|
||||||
|
{
|
||||||
|
l->disctime = DISC_TIME;
|
||||||
|
ast_mutex_lock(&myrpt->lock);
|
||||||
|
ast_hangup(l->chan);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
l->chan = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->retrytimer) break;
|
||||||
|
if (l->outbound && (l->retries++ < MAX_RETRIES))
|
||||||
|
{
|
||||||
|
ast_mutex_lock(&myrpt->lock);
|
||||||
|
ast_hangup(l->chan);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
if (attempt_reconnect(myrpt,l) == -1)
|
||||||
|
{
|
||||||
|
l->retrytimer = RETRY_TIMER_MS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ast_mutex_lock(&myrpt->lock);
|
ast_mutex_lock(&myrpt->lock);
|
||||||
/* remove from queue */
|
/* remove from queue */
|
||||||
remque((struct qelem *) l);
|
remque((struct qelem *) l);
|
||||||
@@ -3519,9 +3708,11 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
{
|
{
|
||||||
if (f->subclass == AST_CONTROL_ANSWER)
|
if (f->subclass == AST_CONTROL_ANSWER)
|
||||||
{
|
{
|
||||||
|
char lconnected = l->connected;
|
||||||
l->connected = 1;
|
l->connected = 1;
|
||||||
l->elaptime = -1;
|
l->elaptime = -1;
|
||||||
rpt_telemetry(myrpt,CONNECTED,l);
|
l->retries = 0;
|
||||||
|
if (!lconnected) rpt_telemetry(myrpt,CONNECTED,l);
|
||||||
}
|
}
|
||||||
/* if RX key */
|
/* if RX key */
|
||||||
if (f->subclass == AST_CONTROL_RADIO_KEY)
|
if (f->subclass == AST_CONTROL_RADIO_KEY)
|
||||||
@@ -3538,6 +3729,30 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
if (f->subclass == AST_CONTROL_HANGUP)
|
if (f->subclass == AST_CONTROL_HANGUP)
|
||||||
{
|
{
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
|
#ifdef RECONNECT_KLUDGE
|
||||||
|
if ((!l->outbound) && (!l->disced))
|
||||||
|
{
|
||||||
|
l->disctime = DISC_TIME;
|
||||||
|
ast_mutex_lock(&myrpt->lock);
|
||||||
|
ast_hangup(l->chan);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
l->chan = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l->retrytimer) break;
|
||||||
|
if (l->outbound && (l->retries++ < MAX_RETRIES))
|
||||||
|
{
|
||||||
|
ast_mutex_lock(&myrpt->lock);
|
||||||
|
ast_hangup(l->chan);
|
||||||
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
if (attempt_reconnect(myrpt,l) == -1)
|
||||||
|
{
|
||||||
|
l->retrytimer = RETRY_TIMER_MS;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ast_mutex_lock(&myrpt->lock);
|
ast_mutex_lock(&myrpt->lock);
|
||||||
/* remove from queue */
|
/* remove from queue */
|
||||||
remque((struct qelem *) l);
|
remque((struct qelem *) l);
|
||||||
@@ -3617,7 +3832,7 @@ char cmd[MAXDTMF+1] = "";
|
|||||||
/* remove from queue */
|
/* remove from queue */
|
||||||
remque((struct qelem *) l);
|
remque((struct qelem *) l);
|
||||||
/* hang-up on call to device */
|
/* hang-up on call to device */
|
||||||
ast_hangup(l->chan);
|
if (l->chan) ast_hangup(l->chan);
|
||||||
ast_hangup(l->pchan);
|
ast_hangup(l->pchan);
|
||||||
l = l->next;
|
l = l->next;
|
||||||
free(ll);
|
free(ll);
|
||||||
@@ -3867,13 +4082,7 @@ static int rpt_exec(struct ast_channel *chan, void *data)
|
|||||||
/* if found */
|
/* if found */
|
||||||
if (l != &myrpt->links)
|
if (l != &myrpt->links)
|
||||||
{
|
{
|
||||||
/* remove from queue */
|
if (l->chan) ast_softhangup(l->chan,AST_SOFTHANGUP_DEV);
|
||||||
remque((struct qelem *) l);
|
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
|
||||||
/* hang-up on call to device */
|
|
||||||
ast_hangup(l->chan);
|
|
||||||
ast_hangup(l->pchan);
|
|
||||||
free(l);
|
|
||||||
usleep(500000);
|
usleep(500000);
|
||||||
} else
|
} else
|
||||||
ast_mutex_unlock(&myrpt->lock);
|
ast_mutex_unlock(&myrpt->lock);
|
||||||
|
Reference in New Issue
Block a user