Newer
Older
Steve Murphy
committed
case GOSUB_NOTFOUND:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/gosub_notfound", mychannel->language);
break;
case MACRO_BUSY:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
break;
Steve Murphy
committed
case GOSUB_BUSY:
/* wait a little bit */
wait_interval(myrpt, DLY_TELEM, mychannel);
res = ast_streamfile(mychannel, "rpt/gosub_busy", mychannel->language);
break;
case UNKEY:
if (myrpt->patchnoct && myrpt->callmode) { /* If no CT during patch configured, then don't send one */
Jim Dixon
committed
imdone = 1;
break;
}
/*
* Reset the Unkey to CT timer
*/
x = get_wait_interval(myrpt, DLY_UNKEY);
rpt_mutex_lock(&myrpt->lock);
myrpt->unkeytocttimer = x; /* Must be protected as it is changed below */
rpt_mutex_unlock(&myrpt->lock);
/*
* If there's one already queued, don't do another
*/
tlist = myrpt->tele.next;
unkeys_queued = 0;
if (tlist != &myrpt->tele) {
rpt_mutex_lock(&myrpt->lock);
while (tlist != &myrpt->tele) {
if (tlist->mode == UNKEY)
unkeys_queued++;
tlist = tlist->next;
}
rpt_mutex_unlock(&myrpt->lock);
}
if (unkeys_queued > 1) {
imdone = 1;
break;
}
/* Wait for the telemetry timer to expire */
/* Periodically check the timer since it can be re-initialized above */
while (myrpt->unkeytocttimer) {
if (myrpt->unkeytocttimer > 100)
ctint = 100;
else
ctint = myrpt->unkeytocttimer;
ast_safe_sleep(mychannel, ctint);
rpt_mutex_lock(&myrpt->lock);
if (myrpt->unkeytocttimer < ctint)
myrpt->unkeytocttimer = 0;
else
myrpt->unkeytocttimer -= ctint;
rpt_mutex_unlock(&myrpt->lock);
}
/*
* Now, the carrier on the rptr rx should be gone.
* If it re-appeared, then forget about sending the CT
*/
if (myrpt->keyed) {
imdone = 1;
break;
}
Jim Dixon
committed
rpt_mutex_lock(&myrpt->lock); /* Update the kerchunk counters */
myrpt->dailykerchunks++;
myrpt->totalkerchunks++;
rpt_mutex_unlock(&myrpt->lock);
hastx = 0;
hasremote = 0;
l = myrpt->links.next;
if (l != &myrpt->links) {
rpt_mutex_lock(&myrpt->lock);
while (l != &myrpt->links) {
if (l->name[0] == '0') {
l = l->next;
continue;
}
haslink = 1;
if (l->mode) {
hastx++;
if (l->isremote)
hasremote++;
l = l->next;
}
rpt_mutex_unlock(&myrpt->lock);
if (haslink) {
res = telem_lookup(myrpt, 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(myrpt, 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(myrpt->cfg, myrpt->name, "unlinkedct"))) { /* Unlinked Courtesy Tone */
res = telem_lookup(myrpt, mychannel, myrpt->name, ct);
if (res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
if (hasremote && (!myrpt->cmdnode[0])) {
/* set for all to hear */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0], ZT_SETCONF, &ci) == -1) {
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_lock(&myrpt->lock);
remque((struct qelem *)mytele);
rpt_mutex_unlock(&myrpt->lock);
ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
ast_free(mytele);
ast_hangup(mychannel);
pthread_exit(NULL);
}
if ((ct = ast_variable_retrieve(myrpt->cfg, myrpt->name, "remotect"))) { /* Unlinked Courtesy Tone */
ast_safe_sleep(mychannel, 200);
res = telem_lookup(myrpt, mychannel, myrpt->name, ct);
if (res)
ast_log(LOG_WARNING, "telem_lookup:ctx failed on %s\n", mychannel->name);
}
}
Jim Dixon
committed
#ifdef _MDC_DECODE_H_
if (myrpt->lastunit) {
Jim Dixon
committed
char mystr[10];
ast_safe_sleep(mychannel, 200);
Jim Dixon
committed
/* set for all to hear */
ci.chan = 0;
ci.confno = myrpt->txconf;
ci.confmode = ZT_CONF_CONFANN;
/* first put the channel on the conference in announce mode */
if (ioctl(mychannel->fds[0], ZT_SETCONF, &ci) == -1) {
Jim Dixon
committed
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
rpt_mutex_lock(&myrpt->lock);
remque((struct qelem *)mytele);
rpt_mutex_unlock(&myrpt->lock);
ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
ast_free(mytele);
Jim Dixon
committed
ast_hangup(mychannel);
pthread_exit(NULL);
}
snprintf(mystr, sizeof(mystr), "%04x", myrpt->lastunit);
Jim Dixon
committed
myrpt->lastunit = 0;
ast_say_character_str(mychannel, mystr, NULL, mychannel->language);
Jim Dixon
committed
break;
}
#endif
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);
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;
rpt_mutex_lock(&myrpt->lock);
/* make our own list of links */
l = myrpt->links.next;
while (l != &myrpt->links) {
if (l->name[0] == '0') {
Tilghman Lesher
committed
m = ast_malloc(sizeof(*m));
if (!m) {
ast_log(LOG_WARNING, "Cannot alloc memory on %s\n", mychannel->name);
rpt_mutex_unlock(&myrpt->lock);
ast_log(LOG_NOTICE, "Telemetry thread aborted at line %d, mode: %d\n", __LINE__, mytele->mode); /*@@@@@@@@@@@*/
ast_free(mytele);
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;
}
rpt_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);
ast_free(m);
}
imdone = 1;
break;
Jim Dixon
committed
case LASTNODEKEY: /* Identify last node which keyed us up */
Jim Dixon
committed
rpt_mutex_lock(&myrpt->lock);
if (myrpt->lastnodewhichkeyedusup)
Jim Dixon
committed
p = ast_strdupa(myrpt->lastnodewhichkeyedusup); /* Make a local copy of the node name */
else
p = NULL;
rpt_mutex_unlock(&myrpt->lock);
if (!p) {
Jim Dixon
committed
imdone = 1; /* no node previously keyed us up, or the node which did has been disconnected */
break;
}
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, p, 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);
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;
case STATS_TIME:
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
tv = ast_tvnow();
ast_localtime(&tv, &localtm, NULL);
/* Say the phase of the day is before the time */
if ((localtm.tm_hour >= 0) && (localtm.tm_hour < 12))
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, tv.tv_sec, "", mychannel->language);
if (!res)
res = ast_waitstream(mychannel, "");
ast_stopstream(mychannel);
imdone = 1;
break;
case STATS_VERSION:
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
if (sayfile(mychannel, "rpt/version") == -1) {
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) {
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 REV_PATCH:
wait_interval(myrpt, DLY_TELEM, mychannel); /* Wait a little bit */
if (mytele->param) {
/* Parts of this section taken from app_parkandannounce */
char *tpl_working, *tpl_current;
char *tmp[100], *myparm;
int looptemp=0, i = 0, dres = 0;
tpl_working = ast_strdupa(mytele->param);
myparm = strsep(&tpl_working, ",");
tpl_current = strsep(&tpl_working, ":");
while (tpl_current && looptemp < sizeof(tmp)) {
tmp[looptemp] = tpl_current;
looptemp++;
tpl_current = strsep(&tpl_working, ":");
}
for (i = 0; i < looptemp; i++) {
if (!strcmp(tmp[i], "PARKED")) {
ast_say_digits(mychannel, atoi(myparm), "", mychannel->language);
} else if (!strcmp(tmp[i], "NODE")) {
ast_say_digits(mychannel, atoi(myrpt->name), "", mychannel->language);
} else {
dres = ast_streamfile(mychannel, tmp[i], mychannel->language);
if (!dres) {
dres = ast_waitstream(mychannel, "");
} else {
ast_log(LOG_WARNING, "ast_streamfile of %s failed on %s\n", tmp[i], mychannel->name);
dres = 0;
}
}
}
}
imdone = 1;
break;
case TEST_TONE:
if ((res = ast_tonepair_start(mychannel, 1004.0, 0, 99999999, 7200.0)))
while (mychannel->generatordata && (!myrpt->stopgen)) {
imdone = 1;
}
break;
default:
}
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);
rpt_mutex_lock(&myrpt->lock);
if (mytele->mode == TAILMSG) {
if (!res) {
myrpt->tailmessagen++;
if (myrpt->tailmessagen >= myrpt->p.tailmsg.argc)
myrpt->tailmessagen = 0;
} else {
Jim Dixon
committed
myrpt->tmsgtimer = myrpt->p.tailsquashedtime;
}
}
remque((struct qelem *)mytele);
rpt_mutex_unlock(&myrpt->lock);
ast_free(mytele);
ast_hangup(mychannel);
#ifdef APP_RPT_LOCK_DEBUG
sleep(5);
ast_mutex_lock(&locklock);
t = get_lockthread(pthread_self());
if (t)
memset(t, 0, sizeof(struct lockthread));
ast_mutex_unlock(&locklock);
#endif
pthread_exit(NULL);
}
static void rpt_telemetry(struct rpt *myrpt, int mode, void *data)
{
struct rpt_tele *tele;
struct rpt_link *mylink = (struct rpt_link *) data;
int res;
Tilghman Lesher
committed
tele = ast_calloc(1, sizeof(*tele));
if (!tele) {
ast_log(LOG_WARNING, "Unable to allocate memory\n");
pthread_exit(NULL);
}
tele->rpt = myrpt;
tele->mode = mode;
rpt_mutex_lock(&myrpt->lock);
if ((mode == CONNFAIL) || (mode == REMDISC) || (mode == CONNECTED)) {
if (mylink) {
memcpy(&tele->mylink, mylink, sizeof(struct rpt_link));
}
} else if ((mode == ARB_ALPHA) || (mode == REV_PATCH)) {
ast_copy_string(tele->param, (char *) data, sizeof(tele->param));
}
Jim Dixon
committed
insque((struct qelem *)tele, (struct qelem *)myrpt->tele.next);
rpt_mutex_unlock(&myrpt->lock);
Russell Bryant
committed
res = ast_pthread_create_detached(&tele->threadid, NULL, rpt_tele_thread, (void *) tele);
if (res != 0) {
Jim Dixon
committed
rpt_mutex_lock(&myrpt->lock);
remque((struct qlem *) tele); /* We don't like stuck transmitters, remove it from the queue */
rpt_mutex_unlock(&myrpt->lock);
ast_log(LOG_WARNING, "Could not create telemetry thread: %s\n", strerror(res));
Jim Dixon
committed
}
return;
}
ZT_CONFINFO ci; /* conference info */
struct rpt *myrpt = (struct rpt *)this;
int res;
struct ast_frame wf;
int stopped, congstarted, dialtimer, lastcidx, aborted;
struct ast_channel *mychannel, *genchannel;
Jim Dixon
committed
myrpt->mydtmf = 0;
/* allocate a pseudo-channel thru asterisk */
mychannel = ast_request("zap", AST_FORMAT_SLINEAR, "pseudo", NULL);
if (!mychannel) {
ast_log(LOG_ERROR, "rpt: unable to obtain pseudo channel\n");
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) {
ast_log(LOG_ERROR, "rpt: 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->p.tonezone && (tone_zone_set_zone(mychannel->fds[0], myrpt->p.tonezone) == -1)) {
ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
if (myrpt->p.tonezone && (tone_zone_set_zone(genchannel->fds[0], myrpt->p.tonezone) == -1)) {
ast_log(LOG_WARNING, "Unable to set tone zone %s\n", myrpt->p.tonezone);
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
Jim Dixon
committed
/* start dialtone if patchquiet is 0. Special patch modes don't send dial tone */
if ((!myrpt->patchquiet) && (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;
Jim Dixon
committed
dialtimer = 0;
lastcidx = 0;
aborted = 0;
while ((myrpt->callmode == 1) || (myrpt->callmode == 4)) {
if ((myrpt->patchdialtime) && (myrpt->callmode == 1) && (myrpt->cidx != lastcidx)) {
Jim Dixon
committed
dialtimer = 0;
lastcidx = myrpt->cidx;
}
if ((myrpt->patchdialtime) && (dialtimer >= myrpt->patchdialtime)) {
Jim Dixon
committed
rpt_mutex_lock(&myrpt->lock);
aborted = 1;
myrpt->callmode = 0;
rpt_mutex_unlock(&myrpt->lock);
break;
}
if ((!myrpt->patchquiet) && (!stopped) && (myrpt->callmode == 1) && (myrpt->cidx > 0)) {
tone_zone_play_tone(mychannel->fds[0], -1);
if (myrpt->callmode == 4) {
if (!congstarted) {
Jim Dixon
committed
congstarted = 1;
/* start congestion tone */
tone_zone_play_tone(mychannel->fds[0], ZT_TONE_CONGESTION);
Jim Dixon
committed
}
if (res < 0) {
ast_hangup(mychannel);
ast_hangup(genchannel);
rpt_mutex_lock(&myrpt->lock);
rpt_mutex_unlock(&myrpt->lock);
Jim Dixon
committed
dialtimer += MSWAIT;
tone_zone_play_tone(mychannel->fds[0], -1);
if (!myrpt->callmode) {
ast_hangup(mychannel);
ast_hangup(genchannel);
rpt_mutex_lock(&myrpt->lock);
rpt_mutex_unlock(&myrpt->lock);
if ((!myrpt->patchquiet) && aborted)
Jim Dixon
committed
rpt_telemetry(myrpt, TERM, NULL);
if (myrpt->p.ourcallerid && *myrpt->p.ourcallerid) {
char *name, *loc, *instr;
instr = ast_strdup(myrpt->p.ourcallerid);
if (instr) {
ast_callerid_parse(instr, &name, &loc);
if (loc) {
if (mychannel->cid.cid_num)
ast_free(mychannel->cid.cid_num);
mychannel->cid.cid_num = ast_strdup(loc);
}
if (name) {
if (mychannel->cid.cid_name)
ast_free(mychannel->cid.cid_name);
mychannel->cid.cid_name = ast_strdup(name);
}
ast_free(instr);
}
ast_copy_string(mychannel->exten, myrpt->exten, sizeof(mychannel->exten));
ast_copy_string(mychannel->context, myrpt->patchcontext, sizeof(mychannel->context));
Jim Dixon
committed
if (myrpt->p.acctcode)
ast_copy_string((char *)mychannel->accountcode, myrpt->p.acctcode, sizeof(mychannel->accountcode));
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);
rpt_mutex_lock(&myrpt->lock);
rpt_mutex_unlock(&myrpt->lock);
rpt_mutex_lock(&myrpt->lock);
Jim Dixon
committed
/* set appropriate conference for the pseudo */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = (myrpt->p.duplex == 2) ? ZT_CONF_CONFANNMON :
(ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
/* first put the channel on the conference in announce mode */
if (ioctl(myrpt->pchannel->fds[0], ZT_SETCONF, &ci) == -1) {
Jim Dixon
committed
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
ast_hangup(mychannel);
ast_hangup(genchannel);
myrpt->callmode = 0;
pthread_exit(NULL);
}
while (myrpt->callmode) {
if ((!mychannel->pbx) && (myrpt->callmode != 4)) {
if (myrpt->patchfarenddisconnect) { /* If patch is setup for far end disconnect */
Jim Dixon
committed
myrpt->callmode = 0;
if (!myrpt->patchquiet) {
Jim Dixon
committed
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, TERM, NULL);
rpt_mutex_lock(&myrpt->lock);
}
} else { /* Send congestion until patch is downed by command */
Jim Dixon
committed
myrpt->callmode = 4;
rpt_mutex_unlock(&myrpt->lock);
/* start congestion tone */
tone_zone_play_tone(genchannel->fds[0], ZT_TONE_CONGESTION);
Jim Dixon
committed
rpt_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;
rpt_mutex_unlock(&myrpt->lock);
ast_write(genchannel, &wf);
rpt_mutex_lock(&myrpt->lock);
rpt_mutex_unlock(&myrpt->lock);
rpt_mutex_lock(&myrpt->lock);
rpt_mutex_unlock(&myrpt->lock);
tone_zone_play_tone(genchannel->fds[0], -1);
if (mychannel->pbx)
ast_softhangup(mychannel, AST_SOFTHANGUP_DEV);
rpt_mutex_lock(&myrpt->lock);
rpt_mutex_unlock(&myrpt->lock);
Jim Dixon
committed
/* set appropriate conference for the pseudo */
ci.chan = 0;
ci.confno = myrpt->conf;
ci.confmode = ((myrpt->p.duplex == 2) || (myrpt->p.duplex == 4)) ? ZT_CONF_CONFANNMON :
(ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER);
/* first put the channel on the conference in announce mode */
if (ioctl(myrpt->pchannel->fds[0], ZT_SETCONF, &ci) == -1) {
Jim Dixon
committed
ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
}
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 (l->name[0] == '0') {
/* if we found it, write it and were done */
wf.data = ast_strdup(str);
if (l->chan)
}
l = l->next;
}
l = myrpt->links.next;
/* if not, give it to everyone */
while (l != &myrpt->links) {
wf.data = ast_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 *digits, int command_source, struct rpt_link *mylink)
{
Tilghman Lesher
committed
const char *val;
char *s, *tele;
char deststr[300] = "", modechange = 0;
char digitbuf[MAXNODESTR];
struct rpt_link *l;
Jim Dixon
committed
int reconnects = 0;
ZT_CONFINFO ci; /* conference info */
AST_DECLARE_APP_ARGS(args,
AST_APP_ARG(s1);
AST_APP_ARG(s2); /* XXX Never used. Scratch? XXX */
);
if (!param)
return DC_ERROR;
if (!myrpt->enable)
return DC_ERROR;
ast_copy_string(digitbuf, digits, sizeof(digitbuf));
ast_debug(1, "@@@@ ilink param = %s, digitbuf = %s\n", S_OR(param, "(null)"), digitbuf);
switch (myatoi(param)) {
case 1: /* Link off */
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
strcpy(digitbuf, myrpt->lastlinknode);
val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val) {
if (strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
break;
}
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
while (l != &myrpt->links) {
if (l->name[0] == '0') {
l = l->next;
continue;
}
/* if found matching string */
if (!strcmp(l->name, digitbuf))
break;
l = l->next;
}
if (l != &myrpt->links) { /* if found */
struct ast_frame wf;
ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
l->retries = MAX_RETRIES + 1;
l->disced = 1;
rpt_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 = ast_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);
}
rpt_telemetry(myrpt, COMPLETE, NULL);
return DC_COMPLETE;
}
rpt_mutex_unlock(&myrpt->lock);
return DC_COMPLETE;
case 2: /* Link Monitor */
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
strcpy(digitbuf, myrpt->lastlinknode);
val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val) {
if (strlen(digitbuf) >= myrpt->longestnode)
return DC_ERROR;
break;
}
s = ast_strdupa(val);
Mark Michelson
committed
AST_STANDARD_APP_ARGS(args, s);
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
while (l != &myrpt->links) {
if (l->name[0] == '0') {
l = l->next;
continue;
}
/* 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 */
if ((!l->mode) || (!l->chan)) {
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, REMALREADY, NULL);
return DC_COMPLETE;
}
reconnects = l->reconnects;
rpt_mutex_unlock(&myrpt->lock);
if (l->chan)
ast_softhangup(l->chan, AST_SOFTHANGUP_DEV);
l->retries = MAX_RETRIES + 1;
l->disced = 2;
modechange = 1;
} else
rpt_mutex_unlock(&myrpt->lock);
ast_copy_string(myrpt->lastlinknode, digitbuf, MAXNODESTR);
/* establish call in monitor mode */
Tilghman Lesher
committed
l = ast_calloc(1, sizeof(*l));
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
if (!l) {
ast_log(LOG_WARNING, "Unable to malloc\n");
return DC_ERROR;
}
snprintf(deststr, sizeof(deststr), "IAX2/%s", args.s1);
tele = strchr(deststr, '/');
if (!tele) {
ast_log(LOG_ERROR, "link2:Dial number (%s) must be in format tech/number\n", deststr);
return DC_ERROR;
}
*tele++ = 0;
l->isremote = (s && ast_true(s));
ast_copy_string(l->name, digitbuf, MAXNODESTR);
l->chan = ast_request(deststr, AST_FORMAT_SLINEAR, tele, NULL);
if (modechange)
l->connected = 1;
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)";
ast_verb(3, "rpt (remote) initiating call to %s/%s on %s\n",
deststr, tele, l->chan->name);
if (l->chan->cid.cid_num)
ast_free(l->chan->cid.cid_num);
l->chan->cid.cid_num = ast_strdup(myrpt->name);
ast_call(l->chan, tele, 0);
} else {
rpt_telemetry(myrpt, CONNFAIL, l);
ast_free(l);
ast_verb(3, "Unable to place call to %s/%s on %s\n",
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
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) {
ast_log(LOG_ERROR, "rpt:Sorry unable to obtain pseudo channel\n");
ast_hangup(l->chan);
ast_free(l);
return DC_ERROR;
}
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);
ast_free(l);
return DC_ERROR;
}
rpt_mutex_lock(&myrpt->lock);
l->reconnects = reconnects;
/* insert at end of queue */
insque((struct qelem *)l, (struct qelem *)myrpt->links.next);
rpt_mutex_unlock(&myrpt->lock);
rpt_telemetry(myrpt, COMPLETE, NULL);
return DC_COMPLETE;
case 3: /* Link transceive */
if ((digitbuf[0] == '0') && (myrpt->lastlinknode[0]))
val = ast_variable_retrieve(myrpt->cfg, myrpt->p.nodes, digitbuf);
if (!val) {
if (strlen(digitbuf) >= myrpt->longestnode)
break;
}
s = ast_strdupa(val);
Mark Michelson
committed
AST_STANDARD_APP_ARGS(args, s);
rpt_mutex_lock(&myrpt->lock);
l = myrpt->links.next;
/* try to find this one in queue */
while (l != &myrpt->links) {
if (l->name[0] == '0') {
l = l->next;
continue;