Newer
Older
ast_safe_sleep(mychannel, ctint);
ast_mutex_lock(&myrpt->lock);
if(myrpt->unkeytocttimer < ctint)
myrpt->unkeytocttimer = 0;
else
myrpt->unkeytocttimer -= ctint;
ast_mutex_unlock(&myrpt->lock);
}
/*
* Now, the carrier on the rptr rx should be gone.
* If it re-appeared, then forget about sending the CT
*/
if(myrpt->keyed){
imdone = 1;
break;
}
hastx = 0;
l = myrpt->links.next;
if (l != &myrpt->links)
{
ast_mutex_lock(&myrpt->lock);
while(l != &myrpt->links)
{
if (l->mode) hastx++;
l = l->next;
}
ast_mutex_unlock(&myrpt->lock);
res = telem_lookup(mychannel, myrpt->name, (!hastx) ? "remotemon" : "remotetx");
if(res)
ast_log(LOG_WARNING, "telem_lookup:remotexx failed on %s\n", mychannel->name);
/* if in remote cmd mode, indicate it */
if (myrpt->cmdnode[0])
{
ast_safe_sleep(mychannel,200);
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);
}
}
else if((ct = ast_variable_retrieve(cfg, nodename, "unlinkedct"))){ /* Unlinked Courtesy Tone */
ct_copy = ast_strdupa(ct);
res = telem_lookup(mychannel, myrpt->name, ct_copy);
if(res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
imdone = 1;
break;
case REMDISC:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
res = ast_streamfile(mychannel, ((mytele->mylink.connected) ?
"rpt/remote_disc" : "rpt/remote_busy"), mychannel->language);
break;
case REMALREADY:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/remote_already", mychannel->language);
break;
case REMNOTFOUND:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/remote_notfound", mychannel->language);
break;
case REMGO:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/remote_go", mychannel->language);
break;
case CONNECTED:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
res = ast_streamfile(mychannel, "rpt/connected", mychannel->language);
break;
case CONNFAIL:
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
ast_say_character_str(mychannel,mytele->mylink.name,NULL,mychannel->language);
res = ast_streamfile(mychannel, "rpt/connection_failed", mychannel->language);
break;
case STATUS:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
hastx = 0;
linkbase.next = &linkbase;
linkbase.prev = &linkbase;
ast_mutex_lock(&myrpt->lock);
/* make our own list of links */
l = myrpt->links.next;
while(l != &myrpt->links)
{
m = malloc(sizeof(struct rpt_link));
if (!m)
{
ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
ast_mutex_lock(&myrpt->lock);
remque((struct qelem *)mytele);
ast_mutex_unlock(&myrpt->lock);
free(mytele);
ast_hangup(mychannel);
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
pthread_exit(NULL);
}
memcpy(m,l,sizeof(struct rpt_link));
m->next = m->prev = NULL;
insque((struct qelem *)m,(struct qelem *)linkbase.next);
l = l->next;
}
ast_mutex_unlock(&myrpt->lock);
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
if (myrpt->callmode)
{
hastx = 1;
res = ast_streamfile(mychannel, "rpt/autopatch_on", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
}
l = linkbase.next;
while(l != &linkbase)
{
hastx = 1;
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
ast_say_character_str(mychannel,l->name,NULL,mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
res = ast_streamfile(mychannel, ((l->mode) ?
"rpt/tranceive" : "rpt/monitor"), mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
l = l->next;
}
if (!hastx)
{
res = ast_streamfile(mychannel, "rpt/repeat_only", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
}
/* destroy our local link queue */
l = linkbase.next;
while(l != &linkbase)
{
m = l;
l = l->next;
remque((struct qelem *)m);
free(m);
}
imdone = 1;
break;
case TIMEOUT:
res = ast_streamfile(mychannel, "rpt/node", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
ast_stopstream(mychannel);
ast_say_character_str(mychannel,myrpt->name,NULL,mychannel->language);
res = ast_streamfile(mychannel, "rpt/timeout", mychannel->language);
break;
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
Jim Dixon
committed
localtime_r(&t, &localtm);
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
/* Say the phase of the day is before the time */
if((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
p = "rpt/goodmorning";
else if((localtm.tm_hour >= 12) && (localtm.tm_hour < 18))
p = "rpt/goodafternoon";
else
p = "rpt/goodevening";
if (sayfile(mychannel,p) == -1)
{
imdone = 1;
break;
}
/* Say the time is ... */
if (sayfile(mychannel,"rpt/thetimeis") == -1)
{
imdone = 1;
break;
}
/* Say the time */
res = ast_say_time(mychannel, t, "", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
imdone = 1;
break;
case STATS_VERSION:
p = strstr(tdesc, "version");
if(!p)
break;
if(sscanf(p, "version %d.%d", &vmajor, &vminor) != 2)
break;
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
/* Say "version" */
if (sayfile(mychannel,"rpt/version") == -1)
{
imdone = 1;
break;
}
if(!res) /* Say "X" */
ast_say_number(mychannel, vmajor, "", mychannel->language, (char *) NULL);
if (!res)
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
if (saycharstr(mychannel,".") == -1)
{
imdone = 1;
break;
}
if(!res) /* Say "Y" */
ast_say_number(mychannel, vminor, "", mychannel->language, (char *) NULL);
if (!res){
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
}
else
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
imdone = 1;
break;
case ARB_ALPHA:
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
if(mytele->param)
saycharstr(mychannel, mytele->param);
imdone = 1;
break;
case TEST_TONE:
imdone = 1;
myrpt->stopgen = 0;
if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
break;
while(mychannel->generatordata && (!myrpt->stopgen)) {
if (ast_safe_sleep(mychannel,1)) break;
imdone = 1;
}
break;
}
if (!imdone)
{
if (!res)
res = ast_waitstream(mychannel, "");
else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
res = 0;
}
}
ast_stopstream(mychannel);
ast_mutex_lock(&myrpt->lock);
remque((struct qelem *)mytele);
ast_mutex_unlock(&myrpt->lock);
free(mytele);
ast_hangup(mychannel);
pthread_exit(NULL);
}
static void rpt_telemetry(struct rpt *myrpt,int mode, void *data)
{
struct rpt_tele *tele;
struct rpt_link *mylink = (struct rpt_link *) data;
pthread_attr_t attr;
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);
if((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)){
memset(&tele->mylink,0,sizeof(struct rpt_link));
if (mylink){
memcpy(&tele->mylink,mylink,sizeof(struct rpt_link));
}
}
else if (mode == ARB_ALPHA){
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);
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ast_pthread_create(&tele->threadid,&attr,rpt_tele_thread,(void *) tele);
return;
}
static void *rpt_call(void *this)
{
ZT_CONFINFO ci; /* conference info */
struct rpt *myrpt = (struct rpt *)this;
int res;
int stopped,congstarted;
struct ast_channel *mychannel,*genchannel;
myrpt->mydtmf = 0;
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
if (!mychannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
pthread_exit(NULL);
}
ci.chan = 0;
ci.confno = myrpt->conf; /* use the pseudo conference */
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
| ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
/* first put the channel on the conference */
if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
/* allocate a pseudo-channel thru asterisk */
genchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
if (!genchannel)
{
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
ast_hangup(mychannel);
pthread_exit(NULL);
}
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_REALANDPSEUDO | ZT_CONF_TALKER | ZT_CONF_LISTENER
| ZT_CONF_PSEUDO_TALKER | ZT_CONF_PSEUDO_LISTENER;
/* first put the channel on the conference */
if (ioctl(genchannel->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
{
ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
{
ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
/* start dialtone */
if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
{
ast_log(LOG_WARNING, "Cannot start dialtone\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
stopped = 0;
congstarted = 0;
while ((myrpt->callmode == 1) || (myrpt->callmode == 4))
{
if ((myrpt->callmode == 1) && (myrpt->cidx > 0) && (!stopped))
{
stopped = 1;
/* stop dial tone */
tone_zone_play_tone(mychannel->fds[0],-1);
}
if ((myrpt->callmode == 4) && (!congstarted))
{
congstarted = 1;
/* start congestion tone */
tone_zone_play_tone(mychannel->fds[0],ZT_TONE_CONGESTION);
}
if (res < 0)
{
ast_hangup(mychannel);
ast_hangup(genchannel);
ast_mutex_lock(&myrpt->lock);
ast_mutex_unlock(&myrpt->lock);
pthread_exit(NULL);
}
}
/* stop any tone generation */
tone_zone_play_tone(mychannel->fds[0],-1);
/* end if done */
if (!myrpt->callmode)
{
ast_hangup(mychannel);
ast_hangup(genchannel);
ast_mutex_lock(&myrpt->lock);
ast_mutex_unlock(&myrpt->lock);
if (myrpt->ourcallerid && *myrpt->ourcallerid){
char *name, *loc, *instr;
instr = strdup(myrpt->ourcallerid);
if(instr){
ast_callerid_parse(instr, &name, &loc);
if(loc){
if(mychannel->cid.cid_num)
free(mychannel->cid.cid_num);
mychannel->cid.cid_num = strdup(loc);
}
if(name){
if(mychannel->cid.cid_name)
free(mychannel->cid.cid_name);
mychannel->cid.cid_name = strdup(name);
}
free(instr);
}
strncpy(mychannel->exten, myrpt->exten, sizeof(mychannel->exten) - 1);
strncpy(mychannel->context, myrpt->ourcontext, sizeof(mychannel->context) - 1);
strncpy(mychannel->accountcode, myrpt->acctcode, sizeof(mychannel->accountcode) - 1);
mychannel->priority = 1;
ast_channel_undefer_dtmf(mychannel);
if (ast_pbx_start(mychannel) < 0)
{
ast_log(LOG_WARNING, "Unable to start PBX!!\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
ast_mutex_lock(&myrpt->lock);
ast_mutex_unlock(&myrpt->lock);
ast_mutex_lock(&myrpt->lock);
myrpt->callmode = 3;
while(myrpt->callmode)
{
if ((!mychannel->pbx) && (myrpt->callmode != 4))
ast_mutex_unlock(&myrpt->lock);
/* start congestion tone */
tone_zone_play_tone(genchannel->fds[0],ZT_TONE_CONGESTION);
ast_mutex_lock(&myrpt->lock);
}
if (myrpt->mydtmf)
{
wf.frametype = AST_FRAME_DTMF;
wf.subclass = myrpt->mydtmf;
wf.offset = 0;
wf.mallocd = 0;
wf.data = NULL;
wf.datalen = 0;
wf.samples = 0;
ast_mutex_unlock(&myrpt->lock);
ast_mutex_lock(&myrpt->lock);
ast_mutex_unlock(&myrpt->lock);
ast_mutex_lock(&myrpt->lock);
ast_mutex_unlock(&myrpt->lock);
if (mychannel->pbx) ast_softhangup(mychannel,AST_SOFTHANGUP_DEV);
ast_mutex_lock(&myrpt->lock);
ast_mutex_unlock(&myrpt->lock);
static void send_link_dtmf(struct rpt *myrpt,char c)
{
char str[300];
struct ast_frame wf;
struct rpt_link *l;
snprintf(str, sizeof(str), "D %s %s %d %c", myrpt->cmdnode, myrpt->name, ++(myrpt->dtmfidx), c);
wf.frametype = AST_FRAME_TEXT;
wf.subclass = 0;
wf.offset = 0;
wf.mallocd = 1;
wf.datalen = strlen(str) + 1;
wf.samples = 0;
l = myrpt->links.next;
/* first, see if our dude is there */
while(l != &myrpt->links)
{
/* if we found it, write it and were done */
if (!strcmp(l->name,myrpt->cmdnode))
{
wf.data = strdup(str);
if (l->chan) ast_write(l->chan,&wf);
}
l = l->next;
}
l = myrpt->links.next;
/* if not, give it to everyone */
while(l != &myrpt->links)
{
wf.data = strdup(str);
if (l->chan) ast_write(l->chan,&wf);
l = l->next;
}
return;
}
/*
* Internet linking function
*/
static int function_ilink(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
{
char *val, *s, *s1, *tele;
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
struct rpt_link *l;
ZT_CONFINFO ci; /* conference info */
if(!param)
return DC_ERROR;
if (!myrpt->enable)
return DC_ERROR;
if(debug)
printf("@@@@ ilink param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
switch(myatoi(param)){
case 1: /* Link off */
val = ast_variable_retrieve(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
break;
}
strncpy(tmp,val,sizeof(tmp) - 1);
s = tmp;
s1 = strsep(&s,",");
ast_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
while(l != &myrpt->links){
/* if found matching string */
if (!strcmp(l->name, digitbuf))
break;
l = l->next;
}
if (l != &myrpt->links){ /* if found */
struct ast_frame wf;
l->retries = MAX_RETRIES + 1;
l->disced = 1;
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);
}
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
rpt_telemetry(myrpt, COMPLETE, NULL);
return DC_COMPLETE;
}
ast_mutex_unlock(&myrpt->lock);
return DC_COMPLETE;
case 2: /* Link Monitor */
val = ast_variable_retrieve(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
break;
}
strncpy(tmp,val,sizeof(tmp) - 1);
s = tmp;
s1 = strsep(&s,",");
ast_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
while(l != &myrpt->links){
/* if found matching string */
if (!strcmp(l->name, digitbuf))
break;
l = l->next;
}
/* if found */
if (l != &myrpt->links)
{
/* if already in this mode, just ignore */
ast_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt,REMALREADY,NULL);
return DC_COMPLETE;
}
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);
/* establish call in monitor mode */
l = malloc(sizeof(struct rpt_link));
if (!l){
ast_log(LOG_WARNING, "Unable to malloc\n");
}
/* zero the silly thing */
memset((char *)l,0,sizeof(struct rpt_link));
snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
tele = strchr(deststr,'/');
if (!tele){
fprintf(stderr,"link2:Dial number (%s) must be in format tech/number\n",deststr);
}
*tele++ = 0;
l->isremote = (s && ast_true(s));
strncpy(l->name, digitbuf, MAXNODESTR - 1);
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 (remote) 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,0);
}
else
{
free(l);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
deststr,tele,l->chan->name);
return DC_ERROR;
}
/* allocate a pseudo-channel thru asterisk */
l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
if (!l->pchan){
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
}
ast_set_read_format(l->pchan,AST_FORMAT_SLINEAR);
ast_set_write_format(l->pchan,AST_FORMAT_SLINEAR);
/* make a conference for the pseudo-one */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
/* first put the channel on the conference in proper mode */
if (ioctl(l->pchan->fds[0],ZT_SETCONF,&ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(l->chan);
ast_hangup(l->pchan);
free(l);
return DC_ERROR;
}
ast_mutex_lock(&myrpt->lock);
/* insert at end of queue */
insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
ast_mutex_unlock(&myrpt->lock);
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
rpt_telemetry(myrpt,COMPLETE,NULL);
return DC_COMPLETE;
case 3: /* Link transceive */
val = ast_variable_retrieve(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
break;
}
strncpy(tmp,val,sizeof(tmp) - 1);
s = tmp;
s1 = strsep(&s,",");
ast_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
while(l != &myrpt->links){
/* if found matching string */
if (!strcmp(l->name, digitbuf))
break;
l = l->next;
}
/* if found */
if (l != &myrpt->links){
/* if already in this mode, just ignore */
ast_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, REMALREADY, NULL);
return DC_COMPLETE;
}
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);
/* establish call in tranceive mode */
l = malloc(sizeof(struct rpt_link));
if (!l){
ast_log(LOG_WARNING, "Unable to malloc\n");
}
/* zero the silly thing */
memset((char *)l,0,sizeof(struct rpt_link));
l->mode = 1;
strncpy(l->name, digitbuf, MAXNODESTR - 1);
l->isremote = (s && ast_true(s));
snprintf(deststr, sizeof(deststr), "IAX2/%s", s1);
tele = strchr(deststr, '/');
if (!tele){
fprintf(stderr,"link3:Dial number (%s) must be in format tech/number\n",deststr);
}
*tele++ = 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 (remote) 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{
free(l);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Unable to place call to %s/%s on %s\n",
deststr,tele,l->chan->name);
return DC_ERROR;
}
/* allocate a pseudo-channel thru asterisk */
l->pchan = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo",NULL);
if (!l->pchan){
fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
}
ast_set_read_format(l->pchan, AST_FORMAT_SLINEAR);
ast_set_write_format(l->pchan, AST_FORMAT_SLINEAR);
/* make a conference for the tx */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER;
/* first put the channel on the conference in proper mode */
if (ioctl(l->pchan->fds[0], ZT_SETCONF, &ci) == -1)
{
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(l->chan);
ast_hangup(l->pchan);
free(l);
return DC_ERROR;
}
ast_mutex_lock(&myrpt->lock);
/* insert at end of queue */
insque((struct qelem *)l,(struct qelem *)myrpt->links.next);
ast_mutex_unlock(&myrpt->lock);
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
rpt_telemetry(myrpt,COMPLETE,NULL);
return DC_COMPLETE;
case 4: /* Enter Command Mode */
/* if doesnt allow link cmd, or no links active, return */
if ((command_source != SOURCE_RPT) || (myrpt->links.next == &myrpt->links))
return DC_COMPLETE;
/* if already in cmd mode, or selected self, fughetabahtit */
if ((myrpt->cmdnode[0]) || (!strcmp(myrpt->name, digitbuf))){
rpt_telemetry(myrpt, REMALREADY, NULL);
return DC_COMPLETE;
}
/* node must at least exist in list */
val = ast_variable_retrieve(cfg, NODES, digitbuf);
if (!val){
if(strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
break;
}
ast_mutex_lock(&myrpt->lock);
strncpy(myrpt->cmdnode, digitbuf, sizeof(myrpt->cmdnode) - 1);
ast_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, REMGO, NULL);
return DC_COMPLETE;
case 5: /* Status */
rpt_telemetry(myrpt, STATUS, NULL);
return DC_COMPLETE;
case 6: /* All Links Off */
l = myrpt->links.next;
while(l != &myrpt->links){
if (l->chan) ast_softhangup(l->chan, AST_SOFTHANGUP_DEV); /* Hang 'em up */
l = l->next;
}
rpt_telemetry(myrpt, COMPLETE, NULL);
break;
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
default:
return DC_ERROR;
}
return DC_INDETERMINATE;
}
/*
* Autopatch up
*/
static int function_autopatchup(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
{
pthread_attr_t attr;
if (!myrpt->enable)
return DC_ERROR;
if(debug)
printf("@@@@ Autopatch up\n");
ast_mutex_lock(&myrpt->lock);
/* if on call, force * into current audio stream */
if ((myrpt->callmode == 2) || (myrpt->callmode == 3)){
myrpt->mydtmf = myrpt->funcchar;
}
if (myrpt->callmode){
ast_mutex_unlock(&myrpt->lock);
return DC_COMPLETE;
}
myrpt->callmode = 1;
myrpt->cidx = 0;
myrpt->exten[myrpt->cidx] = 0;
ast_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 DC_COMPLETE;
}
/*
* Autopatch down
*/
static int function_autopatchdn(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
{
if (!myrpt->enable)
return DC_ERROR;
if(debug)
printf("@@@@ Autopatch down\n");
ast_mutex_lock(&myrpt->lock);
if (!myrpt->callmode){
ast_mutex_unlock(&myrpt->lock);
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
return DC_COMPLETE;
}
myrpt->callmode = 0;
ast_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, TERM, NULL);
return DC_COMPLETE;
}
/*
* Status
*/
static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int command_source)
{
if(!param)
return DC_ERROR;
if (!myrpt->enable)
return DC_ERROR;
if(debug)
printf("@@@@ status param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
switch(myatoi(param)){
case 1: /* System ID */
rpt_telemetry(myrpt, ID1, NULL);
return DC_COMPLETE;
case 2: /* System Time */
rpt_telemetry(myrpt, STATS_TIME, NULL);
return DC_COMPLETE;
case 3: /* app_rpt.c version */
rpt_telemetry(myrpt, STATS_VERSION, NULL);
default:
return DC_ERROR;
}
return DC_INDETERMINATE;
}
/*