*/
/*** MODULEINFO
+ <depend>res_smdi</depend>
<depend>zaptel_vldtmf</depend>
<depend>zaptel</depend>
<depend>tonezone</depend>
#include "asterisk/abstract_jb.h"
#include "asterisk/smdi.h"
#include "asterisk/astobj.h"
+#include "asterisk/event.h"
+
#define SMDI_MD_WAIT_TIMEOUT 1500 /* 1.5 seconds */
/*! Global jitterbuffer configuration - by default, jb is disabled */
#ifdef HAVE_PRI
" w/PRI"
#endif
-#ifdef HAVEL_LIBSS7
+#ifdef HAVEL_SS7
"w/SS7"
#endif
;
#define DCHAN_AVAILABLE (DCHAN_PROVISIONED | DCHAN_NOTINALARM | DCHAN_UP)
+/* Overlap dialing option types */
+#define ZAP_OVERLAPDIAL_NONE 0
+#define ZAP_OVERLAPDIAL_OUTGOING 1
+#define ZAP_OVERLAPDIAL_INCOMING 2
+#define ZAP_OVERLAPDIAL_BOTH (ZAP_OVERLAPDIAL_INCOMING|ZAP_OVERLAPDIAL_OUTGOING)
+
static char defaultcic[64] = "";
static char defaultozz[64] = "";
-static char language[MAX_LANGUAGE] = "";
static char progzone[10] = "";
static int usedistinctiveringdetection = 0;
static int zt_sendtext(struct ast_channel *c, const char *text);
+static void mwi_event_cb(const struct ast_event *event, void *userdata)
+{
+ /* This module does not handle MWI in an event-based manner. However, it
+ * subscribes to MWI for each mailbox that is configured so that the core
+ * knows that we care about it. Then, chan_zap will get the MWI from the
+ * event cache instead of checking the mailbox directly. */
+}
+
/*! \brief Avoid the silly zt_getevent which ignores a bunch of events */
static inline int zt_get_event(int fd)
{
#define LINKSTATE_UP (1 << 2)
#define LINKSTATE_DOWN (1 << 3)
+#define SS7_NAI_DYNAMIC -1
+
struct zt_ss7 {
pthread_t master; /*!< Thread of master */
ast_mutex_t lock;
LINKSET_STATE_DOWN = 0,
LINKSET_STATE_UP
} state;
+ char called_nai; /*!< Called Nature of Address Indicator */
+ char calling_nai; /*!< Calling Nature of Address Indicator */
+ char internationalprefix[10]; /*!< country access code ('00' for european dialplans) */
+ char nationalprefix[10]; /*!< area access code ('0' for european dialplans) */
+ char subscriberprefix[20]; /*!< area access code + area code ('0'+area code for european dialplans) */
+ char unknownprefix[20]; /*!< for unknown dialplans */
struct ss7 *ss7;
struct zt_pvt *pvts[MAX_CHANNELS]; /*!< Member channel pvt structs */
};
int outsigmod; /*!< Outbound Signalling style (modifier) */
int oprmode; /*!< "Operator Services" mode */
struct zt_pvt *oprpeer; /*!< "Operator Services" peer tech_pvt ptr */
+ float cid_rxgain; /*!< "Gain to apply during caller id */
float rxgain;
float txgain;
int tonezone; /*!< tone zone for this chan, or -1 for default */
unsigned int inalarm:1;
unsigned int mate:1; /*!< flag to say its in MATE mode */
unsigned int outgoing:1;
- unsigned int overlapdial:1;
+ /* unsigned int overlapdial:1; unused and potentially confusing */
unsigned int permcallwaiting:1;
unsigned int permhidecallerid:1; /*!< Whether to hide our outgoing caller ID or not */
unsigned int priindication_oob:1;
char callwait_name[AST_MAX_EXTENSION];
char rdnis[AST_MAX_EXTENSION];
char dnid[AST_MAX_EXTENSION];
- unsigned int group;
+ ast_group_t group;
int law;
int confno; /*!< Our conference */
int confusers; /*!< Who is using our conference */
struct tdd_state *tdd; /*!< TDD flag */
char call_forward[AST_MAX_EXTENSION];
char mailbox[AST_MAX_EXTENSION];
+ struct ast_event_sub *mwi_event_sub;
char dialdest[256];
int onhooktime;
int msgstate;
struct isup_call *ss7call;
int transcap;
int cic; /*!< CIC associated with channel */
+ unsigned int dpc; /*!< CIC's DPC */
#endif
char begindigit;
} *iflist = NULL, *ifend = NULL;
* statement is reached, the current zt_chan_conf is used to configure the
* channel (struct zt_pvt)
*
- * @seealso zt_chan_init for the default values.
+ * \see zt_chan_init for the default values.
*/
struct zt_chan_conf {
struct zt_pvt chan;
#ifdef HAVE_PRI
struct zt_pri pri;
#endif
+
+#ifdef HAVE_SS7
+ struct zt_ss7 ss7;
+#endif
ZT_PARAMS timing;
char smdi_port[SMDI_MAX_FILENAME_LEN];
.resetinterval = 3600
},
#endif
+#ifdef HAVE_SS7
+ .ss7 = {
+ .called_nai = SS7_NAI_NATIONAL,
+ .calling_nai = SS7_NAI_NATIONAL,
+ .internationalprefix = "",
+ .nationalprefix = "",
+ .subscriberprefix = "",
+ .unknownprefix = ""
+ },
+#endif
.chan = {
.context = "default",
.cid_num = "",
.sig = -1,
.outsigmod = -1,
+ .cid_rxgain = +5.0,
+
.tonezone = -1,
.echocancel = 1,
int tinthreeway;
struct ast_channel *towner;
- if (option_debug)
- ast_log(LOG_DEBUG, "Swapping %d and %d\n", a, b);
+ ast_debug(1, "Swapping %d and %d\n", a, b);
tchan = p->subs[a].chan;
towner = p->subs[a].owner;
p->subs[x].zfd = -1;
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
+ ast_debug(1, "Allocated %s subchannel on FD %d channel %d\n", subnames[x], p->subs[x].zfd, p->subs[x].chan);
return 0;
} else
ast_log(LOG_WARNING, "Unable to open pseudo channel: %s\n", strerror(errno));
ast_log(LOG_WARNING, "Trying to unalloc the real channel %d?!?\n", p->channel);
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Released sub %d of channel %d\n", x, p->channel);
+ ast_debug(1, "Released sub %d of channel %d\n", x, p->channel);
if (p->subs[x].zfd > -1) {
zt_close(p->subs[x].zfd);
}
ast_log(LOG_WARNING, "Unable to grab PRI on span %d\n", pvt->span);
} else if (strlen(pvt->dialdest) < sizeof(pvt->dialdest) - 1) {
int res;
- if (option_debug)
- ast_log(LOG_DEBUG, "Queueing digit '%c' since setup_ack not yet received\n", digit);
+ ast_debug(1, "Queueing digit '%c' since setup_ack not yet received\n", digit);
res = strlen(pvt->dialdest);
pvt->dialdest[res++] = digit;
pvt->dialdest[res] = '\0';
else
pvt->dialing = 1;
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Started VLDTMF digit '%c'\n", digit);
+ ast_debug(1, "Started VLDTMF digit '%c'\n", digit);
pvt->dialing = 1;
pvt->begindigit = digit;
}
if (pvt->begindigit) {
x = -1;
- if (option_debug)
- ast_log(LOG_DEBUG, "Ending VLDTMF digit '%c'\n", digit);
+ ast_debug(1, "Ending VLDTMF digit '%c'\n", digit);
res = ioctl(pvt->subs[SUB_REAL].zfd, ZT_SENDTONE, &x);
pvt->dialing = 0;
pvt->begindigit = 0;
#ifdef HAVE_PRI
static char *dialplan2str(int dialplan)
{
- if (dialplan == -1) {
+ if (dialplan == -1 || dialplan == -2) {
return("Dynamically set dialplan in ISDN");
}
return (pri_plan2str(dialplan));
p->confno = zi.confno;
}
memcpy(&c->curconf, &zi, sizeof(c->curconf));
- if (option_debug)
- ast_log(LOG_DEBUG, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
+ ast_debug(1, "Added %d to conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
return 0;
}
ast_log(LOG_WARNING, "Failed to drop %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
+ ast_debug(1, "Removed %d from conference %d/%d\n", c->zfd, c->curconf.confmode, c->curconf.confno);
memcpy(&c->curconf, &zi, sizeof(c->curconf));
return 0;
}
Kill it. */
p->confno = -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
+ ast_debug(1, "Updated conferencing on %d, with %d conference users\n", p->channel, needconf);
return 0;
}
if (!p)
return;
if (p->echocanon) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Echo cancellation already on\n");
+ ast_debug(1, "Echo cancellation already on\n");
return;
}
if (p->digital) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Echo cancellation isn't required on digital connection\n");
+ ast_debug(1, "Echo cancellation isn't required on digital connection\n");
return;
}
if (p->echocancel) {
ast_log(LOG_WARNING, "Unable to enable echo cancellation on channel %d\n", p->channel);
else {
p->echocanon = 1;
- if (option_debug)
- ast_log(LOG_DEBUG, "Enabled echo cancellation on channel %d\n", p->channel);
+ ast_debug(1, "Enabled echo cancellation on channel %d\n", p->channel);
}
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "No echo cancellation requested\n");
- }
+ } else
+ ast_debug(1, "No echo cancellation requested\n");
}
static void zt_train_ec(struct zt_pvt *p)
res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOTRAIN, &x);
if (res)
ast_log(LOG_WARNING, "Unable to request echo training on channel %d\n", p->channel);
- else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Engaged echo training on channel %d\n", p->channel);
- }
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "No echo training requested\n");
- }
+ else
+ ast_debug(1, "Engaged echo training on channel %d\n", p->channel);
+ } else
+ ast_debug(1, "No echo training requested\n");
}
static void zt_disable_ec(struct zt_pvt *p)
res = ioctl(p->subs[SUB_REAL].zfd, ZT_ECHOCANCEL, &x);
if (res)
ast_log(LOG_WARNING, "Unable to disable echo cancellation on channel %d\n", p->channel);
- else {
- if (option_debug)
- ast_log(LOG_DEBUG, "disabled echo cancellation on channel %d\n", p->channel);
- }
+ else
+ ast_debug(1, "disabled echo cancellation on channel %d\n", p->channel);
}
p->echocanon = 0;
}
g.chan = chan;
res = ioctl(fd, ZT_GETGAINS, &g);
if (res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
+ ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
return res;
}
g.chan = chan;
res = ioctl(fd, ZT_GETGAINS, &g);
if (res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
+ ast_debug(1, "Failed to read gains: %s\n", strerror(errno));
return res;
}
{
int res;
- /* Bump receive gain by 5.0db */
- res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + 5.0, p->txgain, p->law);
+ /* Bump receive gain by value stored in cid_rxgain */
+ res = set_actual_gain(p->subs[SUB_REAL].zfd, 0, p->rxgain + p->cid_rxgain, p->txgain, p->law);
if (res) {
ast_log(LOG_WARNING, "Unable to bump gain: %s\n", strerror(errno));
return -1;
static inline int zt_set_hook(int fd, int hs)
{
- int x, res;
+ int x, res, count = 0;
+
x = hs;
res = ioctl(fd, ZT_HOOK, &x);
- if (res < 0)
- {
+
+ while (res < 0 && count < 20) {
+ usleep(100000); /* 1/10 sec. */
+ x = hs;
+ res = ioctl(fd, ZT_HOOK, &x);
+ count++;
+ }
+
+ if (res < 0) {
if (errno == EINPROGRESS) return 0;
ast_log(LOG_WARNING, "zt hook failed: %s\n", strerror(errno));
}
+
return res;
}
ast_log(LOG_WARNING, "Unable to set conference info: %s\n", strerror(errno));
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Disabled conferencing\n");
+ ast_debug(1, "Disabled conferencing\n");
return 0;
}
return -1;
}
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Restored conferencing\n");
+ ast_debug(1, "Restored conferencing\n");
return 0;
}
static int has_voicemail(struct zt_pvt *p)
{
+ int new_msgs;
+ struct ast_event *event;
+
+ event = ast_event_get_cached(AST_EVENT_MWI,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, p->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
- return ast_app_has_voicemail(p->mailbox, NULL);
+ if (event) {
+ new_msgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
+ ast_event_destroy(event);
+ } else
+ new_msgs = ast_app_has_voicemail(p->mailbox, NULL);
+
+ return new_msgs;
}
static int send_callerid(struct zt_pvt *p)
return 0;
p->cidpos += res;
}
- free(p->cidspill);
+ ast_free(p->cidspill);
p->cidspill = NULL;
if (p->callwaitcas) {
/* Wait for CID/CW to expire */
p->callwaitingrepeat = CALLWAITING_REPEAT_SAMPLES;
if (p->cidspill) {
ast_log(LOG_WARNING, "Spill already exists?!?\n");
- free(p->cidspill);
+ ast_free(p->cidspill);
}
if (!(p->cidspill = ast_malloc(2400 /* SAS */ + 680 /* CAS */ + READ_SIZE * 4)))
return -1;
return 0;
}
+#ifdef HAVE_SS7
+static unsigned char cid_pres2ss7pres(int cid_pres)
+{
+ return (cid_pres >> 5) & 0x03;
+}
+
+static unsigned char cid_pres2ss7screen(int cid_pres)
+{
+ return cid_pres & 0x03;
+}
+#endif
+
static int zt_call(struct ast_channel *ast, char *rdest, int timeout)
{
struct zt_pvt *p = ast->tech_pvt;
/* Generate the Caller-ID spill if desired */
if (p->cidspill) {
ast_log(LOG_WARNING, "cidspill already exists??\n");
- free(p->cidspill);
+ ast_free(p->cidspill);
}
p->callwaitcas = 0;
if ((p->cidspill = ast_malloc(MAX_CALLERID_SIZE))) {
if (c) {
p->dop.op = ZT_DIAL_OP_REPLACE;
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "Tw%s", c);
- if (option_debug)
- ast_log(LOG_DEBUG, "FXO: setup deferred dialstring: %s\n", c);
+ ast_debug(1, "FXO: setup deferred dialstring: %s\n", c);
} else {
p->dop.dialstr[0] = '\0';
}
#ifdef HAVE_PRI
}
#endif
- if (option_debug)
- ast_log(LOG_DEBUG, "Dialing '%s'\n", c);
+ ast_debug(1, "Dialing '%s'\n", c);
p->dop.op = ZT_DIAL_OP_REPLACE;
c += p->stripmsd;
ast_mutex_unlock(&p->lock);
return -1;
}
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Deferring dialing...\n");
- }
+ } else
+ ast_debug(1, "Deferring dialing...\n");
+
p->dialing = 1;
if (ast_strlen_zero(c))
p->dialednone = 1;
p->dialdest[0] = '\0';
break;
default:
- if (option_debug)
- ast_log(LOG_DEBUG, "not yet implemented\n");
+ ast_debug(1, "not yet implemented\n");
ast_mutex_unlock(&p->lock);
return -1;
}
#ifdef HAVE_SS7
if (p->ss7) {
+ char ss7_called_nai;
+ int called_nai_strip;
+ char ss7_calling_nai;
+ int calling_nai_strip;
+
c = strchr(dest, '/');
if (c)
c++;
l = NULL;
}
- ss7_grab(p, p->ss7);
+ if (ss7_grab(p, p->ss7)) {
+ ast_log(LOG_WARNING, "Failed to grab SS7!\n");
+ ast_mutex_unlock(&p->lock);
+ return -1;
+ }
p->digital = IS_DIGITAL(ast->transfercapability);
p->ss7call = isup_new_call(p->ss7->ss7);
return -1;
}
- isup_init_call(p->ss7->ss7, p->ss7call, p->cic, c + p->stripmsd, l);
+ called_nai_strip = 0;
+ ss7_called_nai = p->ss7->called_nai;
+ if (ss7_called_nai == SS7_NAI_DYNAMIC) { /* compute dynamically */
+ if (strncmp(c + p->stripmsd, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
+ called_nai_strip = strlen(p->ss7->internationalprefix);
+ ss7_called_nai = SS7_NAI_INTERNATIONAL;
+ } else if (strncmp(c + p->stripmsd, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
+ called_nai_strip = strlen(p->ss7->nationalprefix);
+ ss7_called_nai = SS7_NAI_NATIONAL;
+ } else {
+ ss7_called_nai = SS7_NAI_SUBSCRIBER;
+ }
+ }
+ isup_set_called(p->ss7call, c + p->stripmsd + called_nai_strip, ss7_called_nai, p->ss7->ss7);
+
+ calling_nai_strip = 0;
+ ss7_calling_nai = p->ss7->calling_nai;
+ if ((l != NULL) && (ss7_calling_nai == SS7_NAI_DYNAMIC)) { /* compute dynamically */
+ if (strncmp(l, p->ss7->internationalprefix, strlen(p->ss7->internationalprefix)) == 0) {
+ calling_nai_strip = strlen(p->ss7->internationalprefix);
+ ss7_calling_nai = SS7_NAI_INTERNATIONAL;
+ } else if (strncmp(l, p->ss7->nationalprefix, strlen(p->ss7->nationalprefix)) == 0) {
+ calling_nai_strip = strlen(p->ss7->nationalprefix);
+ ss7_calling_nai = SS7_NAI_NATIONAL;
+ } else {
+ ss7_calling_nai = SS7_NAI_SUBSCRIBER;
+ }
+ }
+ isup_set_calling(p->ss7call, l ? (l + calling_nai_strip) : NULL, ss7_calling_nai,
+ p->use_callingpres ? cid_pres2ss7pres(ast->cid.cid_pres) : (l ? SS7_PRESENTATION_ALLOWED : SS7_PRESENTATION_RESTRICTED),
+ p->use_callingpres ? cid_pres2ss7screen(ast->cid.cid_pres) : SS7_SCREENING_USER_PROVIDED );
+
+ isup_init_call(p->ss7->ss7, p->ss7call, p->cic, p->dpc);
isup_iam(p->ss7->ss7, p->ss7call);
+ ast_setstate(ast, AST_STATE_DIALING);
ss7_rel(p->ss7);
}
#endif /* HAVE_SS7 */
}
if (p->bearer || (mysig == SIG_FXSKS)) {
if (p->bearer) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
+ ast_debug(1, "Oooh, I have a bearer on %d (%d:%d)\n", PVT_TO_CHANNEL(p->bearer), p->bearer->logicalspan, p->bearer->channel);
p->bearer->call = p->call;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "I'm being setup with no bearer right now...\n");
- }
+ } else
+ ast_debug(1, "I'm being setup with no bearer right now...\n");
+
pri_set_crv(p->pri->pri, p->call, p->channel, 0);
}
p->digital = IS_DIGITAL(ast->transfercapability);
ast_verbose(VERBOSE_PREFIX_3 "Requested transfer capability: 0x%.2x - %s\n", ast->transfercapability, ast_transfercapability2str(ast->transfercapability));
dp_strip = 0;
pridialplan = p->pri->dialplan - 1;
- if (pridialplan == -2) { /* compute dynamically */
+ if (pridialplan == -2 || pridialplan == -3) { /* compute dynamically */
if (strncmp(c + p->stripmsd, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
- dp_strip = strlen(p->pri->internationalprefix);
+ if (pridialplan == -2) {
+ dp_strip = strlen(p->pri->internationalprefix);
+ }
pridialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(c + p->stripmsd, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
- dp_strip = strlen(p->pri->nationalprefix);
+ if (pridialplan == -2) {
+ dp_strip = strlen(p->pri->nationalprefix);
+ }
pridialplan = PRI_NATIONAL_ISDN;
} else {
pridialplan = PRI_LOCAL_ISDN;
ldp_strip = 0;
prilocaldialplan = p->pri->localdialplan - 1;
- if ((l != NULL) && (prilocaldialplan == -2)) { /* compute dynamically */
+ if ((l != NULL) && (prilocaldialplan == -2 || prilocaldialplan == -3)) { /* compute dynamically */
if (strncmp(l, p->pri->internationalprefix, strlen(p->pri->internationalprefix)) == 0) {
- ldp_strip = strlen(p->pri->internationalprefix);
+ if (prilocaldialplan == -2) {
+ ldp_strip = strlen(p->pri->internationalprefix);
+ }
prilocaldialplan = PRI_INTERNATIONAL_ISDN;
} else if (strncmp(l, p->pri->nationalprefix, strlen(p->pri->nationalprefix)) == 0) {
- ldp_strip = strlen(p->pri->nationalprefix);
+ if (prilocaldialplan == -2) {
+ ldp_strip = strlen(p->pri->nationalprefix);
+ }
prilocaldialplan = PRI_NATIONAL_ISDN;
} else {
prilocaldialplan = PRI_LOCAL_ISDN;
p->next->prev = p->prev;
if (p->use_smdi)
ASTOBJ_UNREF(p->smdi_iface, ast_smdi_interface_destroy);
+ if (p->mwi_event_sub)
+ ast_event_unsubscribe(p->mwi_event_sub);
ast_mutex_destroy(&p->lock);
- free(p);
+ ast_free(p);
*pvt = NULL;
}
char *digits = (char *) data;
if (ast_strlen_zero(digits)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "No digit string sent to application!\n");
+ ast_debug(1, "No digit string sent to application!\n");
return -1;
}
p = (struct zt_pvt *)chan->tech_pvt;
if (!p) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to find technology private\n");
+ ast_debug(1, "Unable to find technology private\n");
return -1;
}
ast_mutex_lock(&p->lock);
if (!p->pri || !p->call) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to find pri or call on channel!\n");
+ ast_debug(1, "Unable to find pri or call on channel!\n");
ast_mutex_unlock(&p->lock);
return -1;
}
pri_keypad_facility(p->pri->pri, p->call, digits);
pri_rel(p->pri);
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Unable to grab pri to send keypad facility!\n");
+ ast_debug(1, "Unable to grab pri to send keypad facility!\n");
ast_mutex_unlock(&p->lock);
return -1;
}
struct zt_pvt *prev = NULL;
ZT_PARAMS par;
- if (option_debug)
- ast_log(LOG_DEBUG, "zt_hangup(%s)\n", ast->name);
+ ast_debug(1, "zt_hangup(%s)\n", ast->name);
if (!ast->tech_pvt) {
ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
return 0;
restore_gains(p);
if (p->origcid_num) {
ast_copy_string(p->cid_num, p->origcid_num, sizeof(p->cid_num));
- free(p->origcid_num);
+ ast_free(p->origcid_num);
p->origcid_num = NULL;
}
if (p->origcid_name) {
ast_copy_string(p->cid_name, p->origcid_name, sizeof(p->cid_name));
- free(p->origcid_name);
+ ast_free(p->origcid_name);
p->origcid_name = NULL;
}
if (p->dsp)
if (p->exten)
p->exten[0] = '\0';
- if (option_debug)
- ast_log(LOG_DEBUG, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
- p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
+ ast_debug(1, "Hangup: channel: %d index = %d, normal = %d, callwait = %d, thirdcall = %d\n",
+ p->channel, index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
p->ignoredtmf = 0;
if (index > -1) {
zt_setlinear(p->subs[index].zfd, 0);
if (index == SUB_REAL) {
if ((p->subs[SUB_CALLWAIT].zfd > -1) && (p->subs[SUB_THREEWAY].zfd > -1)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Normal call hung up with both three way call and a call waiting call in place?\n");
+ ast_debug(1, "Normal call hung up with both three way call and a call waiting call in place?\n");
if (p->subs[SUB_CALLWAIT].inthreeway) {
/* We had flipped over to answer a callwait and now it's gone */
- if (option_debug)
- ast_log(LOG_DEBUG, "We were flipped over to the callwait, moving back and unowning.\n");
+ ast_debug(1, "We were flipped over to the callwait, moving back and unowning.\n");
/* Move to the call-wait, but un-own us until they flip back. */
swap_subs(p, SUB_CALLWAIT, SUB_REAL);
unalloc_sub(p, SUB_CALLWAIT);
p->owner = NULL;
} else {
/* The three way hung up, but we still have a call wait */
- if (option_debug)
- ast_log(LOG_DEBUG, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
+ ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
swap_subs(p, SUB_THREEWAY, SUB_REAL);
unalloc_sub(p, SUB_THREEWAY);
if (p->subs[SUB_REAL].inthreeway) {
/* This was part of a three way call. Immediately make way for
another call */
- if (option_debug)
- ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
+ ast_debug(1, "Call was complete, setting owner to former third call\n");
p->owner = p->subs[SUB_REAL].owner;
} else {
/* This call hasn't been completed yet... Set owner to NULL */
- if (option_debug)
- ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
+ ast_debug(1, "Call was incomplete, setting owner to NULL\n");
p->owner = NULL;
}
p->subs[SUB_REAL].inthreeway = 0;
if (p->subs[SUB_REAL].inthreeway) {
/* This was part of a three way call. Immediately make way for
another call */
- if (option_debug)
- ast_log(LOG_DEBUG, "Call was complete, setting owner to former third call\n");
+ ast_debug(1, "Call was complete, setting owner to former third call\n");
p->owner = p->subs[SUB_REAL].owner;
} else {
/* This call hasn't been completed yet... Set owner to NULL */
- if (option_debug)
- ast_log(LOG_DEBUG, "Call was incomplete, setting owner to NULL\n");
+ ast_debug(1, "Call was incomplete, setting owner to NULL\n");
p->owner = NULL;
}
p->subs[SUB_REAL].inthreeway = 0;
if (p->ss7call) {
if (!ss7_grab(p, p->ss7)) {
if (!p->alreadyhungup) {
- isup_rel(p->ss7->ss7, p->ss7call, ast->hangupcause ? ast->hangupcause : -1);
+ const char *cause = pbx_builtin_getvar_helper(ast,"SS7_CAUSE");
+ int icause = ast->hangupcause ? ast->hangupcause : -1;
+
+ if (cause) {
+ if (atoi(cause))
+ icause = atoi(cause);
+ }
+ isup_rel(p->ss7->ss7, p->ss7call, icause);
ss7_rel(p->ss7);
p->alreadyhungup = 1;
} else
if (p->call && (!p->bearer || (p->bearer->call == p->call))) {
if (!pri_grab(p, p->pri)) {
if (p->alreadyhungup) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Already hungup... Calling hangup once, and clearing call\n");
+ ast_debug(1, "Already hungup... Calling hangup once, and clearing call\n");
#ifdef SUPPORT_USERUSER
pri_call_set_useruser(p->call, useruser);
} else {
const char *cause = pbx_builtin_getvar_helper(ast,"PRI_CAUSE");
int icause = ast->hangupcause ? ast->hangupcause : -1;
- if (option_debug)
- ast_log(LOG_DEBUG, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
+ ast_debug(1, "Not yet hungup... Calling hangup once with icause, and clearing call\n");
#ifdef SUPPORT_USERUSER
pri_call_set_useruser(p->call, useruser);
}
} else {
if (p->bearer)
- if (option_debug)
- ast_log(LOG_DEBUG, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
+ ast_debug(1, "Bearer call is %p, while ours is still %p\n", p->bearer->call, p->call);
p->call = NULL;
res = 0;
}
res = ioctl(p->subs[SUB_REAL].zfd, ZT_GET_PARAMS, &par);
if (!res) {
#if 0
- if (option_debug)
- ast_log(LOG_DEBUG, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
+ ast_debug(1, "Hanging up channel %d, offhook = %d\n", p->channel, par.rxisoffhook);
#endif
/* If they're off hook, try playing congestion */
if ((par.rxisoffhook) && (!(p->radio || (p->oprmode < 0))))
tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
}
if (p->cidspill)
- free(p->cidspill);
+ ast_free(p->cidspill);
if (p->sig)
zt_disable_ec(p);
x = 0;
}
#ifdef HAVE_PRI
if (p->bearer) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Freeing up bearer channel %d\n", p->bearer->channel);
+ ast_debug(1, "Freeing up bearer channel %d\n", p->bearer->channel);
/* Free up the bearer channel as well, and
don't use its file descriptor anymore */
update_conf(p->bearer);
p->oprmode = 0;
ast->tech_pvt = NULL;
ast_mutex_unlock(&p->lock);
+ ast_module_unref(ast_module_info->self);
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Hungup '%s'\n", ast->name);
case SIG_FXOGS:
case SIG_FXOKS:
/* Pick up the line */
- if (option_debug)
- ast_log(LOG_DEBUG, "Took %s off hook\n", ast->name);
+ ast_debug(1, "Took %s off hook\n", ast->name);
if (p->hanguponpolarityswitch) {
- gettimeofday(&p->polaritydelaytv, NULL);
+ p->polaritydelaytv = ast_tvnow();
}
res = zt_set_hook(p->subs[SUB_REAL].zfd, ZT_OFFHOOK);
tone_zone_play_tone(p->subs[index].zfd, -1);
p->dialing = 0;
if ((index == SUB_REAL) && p->subs[SUB_THREEWAY].inthreeway) {
if (oldstate == AST_STATE_RINGING) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Finally swapping real and threeway\n");
+ ast_debug(1, "Finally swapping real and threeway\n");
tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, -1);
swap_subs(p, SUB_THREEWAY, SUB_REAL);
p->owner = p->subs[SUB_REAL].owner;
ast_log(LOG_WARNING, "No index in TXGAIN?\n");
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
+ ast_debug(1, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
case AST_OPTION_RXGAIN:
scp = (signed char *) data;
ast_log(LOG_WARNING, "No index in RXGAIN?\n");
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
+ ast_debug(1, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
case AST_OPTION_TONE_VERIFY:
if (!p->dsp)
cp = (char *) data;
switch (*cp) {
case 1:
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
+ ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
break;
case 2:
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
+ ast_debug(1, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
break;
default:
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
+ ast_debug(1, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
break;
}
cp = (char *) data;
p->mate = 0;
if (!*cp) { /* turn it off */
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
+ ast_debug(1, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
if (p->tdd)
tdd_free(p->tdd);
p->tdd = 0;
break;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
- (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
+ ast_debug(1, "Set option TDD MODE, value: %s(%d) on %s\n",
+ (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
zt_disable_ec(p);
/* otherwise, turn it on */
if (!p->didtdd) { /* if havent done it yet */
fds[0].revents = 0;
res = poll(fds, 1, -1);
if (!res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
+ ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
continue;
}
/* if got exception */
if (fds[0].revents & POLLPRI)
return -1;
if (!(fds[0].revents & POLLOUT)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
+ ast_debug(1, "write fd not ready on channel %d\n", p->channel);
continue;
}
res = write(fd, buf, size);
if (res != size) {
if (res == -1) return -1;
- if (option_debug)
- ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
+ ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
break;
}
len -= size;
if (!p->dsp)
break;
cp = (char *) data;
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
- *cp ? "ON" : "OFF", (int) *cp, chan->name);
+ ast_debug(1, "Set option RELAX DTMF, value: %s(%d) on %s\n",
+ *cp ? "ON" : "OFF", (int) *cp, chan->name);
ast_dsp_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
break;
case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
cp = (char *) data;
if (!*cp) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
+ ast_debug(1, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
x = 0;
zt_disable_ec(p);
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
+ ast_debug(1, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
x = 1;
}
if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
pp->oprmode = oprmode->mode;
p->oprmode = -oprmode->mode;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Set Operator Services mode, value: %d on %s/%s\n",
- oprmode->mode, chan->name,oprmode->peer->name);
+ ast_debug(1, "Set Operator Services mode, value: %d on %s/%s\n",
+ oprmode->mode, chan->name,oprmode->peer->name);
break;
case AST_OPTION_ECHOCAN:
cp = (char *) data;
if (*cp) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Enabling echo cancelation on %s\n", chan->name);
+ ast_debug(1, "Enabling echo cancelation on %s\n", chan->name);
zt_enable_ec(p);
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Disabling echo cancelation on %s\n", chan->name);
+ ast_debug(1, "Disabling echo cancelation on %s\n", chan->name);
zt_disable_ec(p);
}
break;
if (master->slaves[x]) {
if (!slave || (master->slaves[x] == slave)) {
/* Take slave out of the conference */
- if (option_debug)
- ast_log(LOG_DEBUG, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
+ ast_debug(1, "Unlinking slave %d from %d\n", master->slaves[x]->channel, master->channel);
conf_del(master, &master->slaves[x]->subs[SUB_REAL], SUB_REAL);
conf_del(master->slaves[x], &master->subs[SUB_REAL], SUB_REAL);
master->slaves[x]->master = NULL;
ast_log(LOG_WARNING, "Replacing master %d with new master, %d\n", slave->master->channel, master->channel);
slave->master = master;
- if (option_debug)
- ast_log(LOG_DEBUG, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
+ ast_debug(1, "Making %d slave to master %d at %d\n", slave->channel, master->channel, x);
}
static void disable_dtmf_detect(struct zt_pvt *p)
nothingok = 0;
}
}
- if (option_debug)
- ast_log(LOG_DEBUG, "master: %d, slave: %d, nothingok: %d\n",
- master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
+ ast_debug(1, "master: %d, slave: %d, nothingok: %d\n",
+ master ? master->channel : 0, slave ? slave->channel : 0, nothingok);
if (master && slave) {
/* Stop any tones, or play ringtone as appropriate. If they're bridged
in an active threeway call with a channel that is ringing, we should
p1->subs[SUB_REAL].owner &&
p1->subs[SUB_REAL].inthreeway &&
(p1->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
+ ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c0->name, c1->name);
tone_zone_play_tone(p0->subs[oi0].zfd, ZT_TONE_RINGTONE);
os1 = p1->subs[SUB_REAL].owner->_state;
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
+ ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p0->channel, oi0, p1->channel, oi1);
tone_zone_play_tone(p0->subs[oi0].zfd, -1);
}
if ((oi0 == SUB_THREEWAY) &&
p0->subs[SUB_REAL].owner &&
p0->subs[SUB_REAL].inthreeway &&
(p0->subs[SUB_REAL].owner->_state == AST_STATE_RINGING)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
+ ast_debug(1, "Playing ringback on %s since %s is in a ringing three-way\n", c1->name, c0->name);
tone_zone_play_tone(p1->subs[oi1].zfd, ZT_TONE_RINGTONE);
os0 = p0->subs[SUB_REAL].owner->_state;
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
+ ast_debug(1, "Stopping tones on %d/%d talking to %d/%d\n", p1->channel, oi1, p0->channel, oi0);
tone_zone_play_tone(p1->subs[oi0].zfd, -1);
}
if ((oi0 == SUB_REAL) && (oi1 == SUB_REAL)) {
(t1 != p1->subs[SUB_REAL].inthreeway) ||
(oi0 != i0) ||
(oi1 != i1)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
- op0->channel, oi0, op1->channel, oi1);
+ ast_debug(1, "Something changed out on %d/%d to %d/%d, returning -3 to restart\n",
+ op0->channel, oi0, op1->channel, oi1);
res = AST_BRIDGE_RETRY;
goto return_from_bridge;
}
who = ast_waitfor_n(priority ? c0_priority : c1_priority, 2, &timeoutms);
if (!who) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Ooh, empty read...\n");
+ ast_debug(1, "Ooh, empty read...\n");
continue;
}
f = ast_read(who);
struct zt_pvt *p = newchan->tech_pvt;
int x;
ast_mutex_lock(&p->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "New owner for channel %d is %s\n", p->channel, newchan->name);
+ ast_debug(1, "New owner for channel %d is %s\n", p->channel, newchan->name);
if (p->owner == oldchan) {
p->owner = newchan;
}
/* Tell the caller not to hangup */
return 1;
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
- p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
+ ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
+ p->subs[SUB_REAL].owner->name, p->subs[SUB_THREEWAY].owner->name);
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
return -1;
}
}
return zi.alarms;
}
+
+static void zt_handle_dtmfup(struct ast_channel *ast, int index, struct ast_frame **dest)
+{
+ struct zt_pvt *p = ast->tech_pvt;
+ struct ast_frame *f = *dest;
+
+ ast_debug(1, "DTMF digit: %c on %s\n", f->subclass, ast->name);
+
+ if (p->confirmanswer) {
+ ast_debug(1, "Confirm answer on %s!\n", ast->name);
+ /* Upon receiving a DTMF digit, consider this an answer confirmation instead
+ of a DTMF digit */
+ p->subs[index].f.frametype = AST_FRAME_CONTROL;
+ p->subs[index].f.subclass = AST_CONTROL_ANSWER;
+ *dest = &p->subs[index].f;
+ /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
+ p->confirmanswer = 0;
+ } else if (p->callwaitcas) {
+ if ((f->subclass == 'A') || (f->subclass == 'D')) {
+ ast_debug(1, "Got some DTMF, but it's for the CAS\n");
+ if (p->cidspill)
+ ast_free(p->cidspill);
+ send_cwcidspill(p);
+ }
+ if ((f->subclass != 'm') && (f->subclass != 'u'))
+ p->callwaitcas = 0;
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ *dest = &p->subs[index].f;
+ } else if (f->subclass == 'f') {
+ /* Fax tone -- Handle and return NULL */
+ if ((p->callprogress & 0x6) && !p->faxhandled) {
+ p->faxhandled++;
+ if (strcmp(ast->exten, "fax")) {
+ const char *target_context = S_OR(ast->macrocontext, ast->context);
+
+ if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
+ if (option_verbose > 2)
+ ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
+ /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
+ pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
+ if (ast_async_goto(ast, target_context, "fax", 1))
+ ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
+ } else
+ ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
+ } else
+ ast_debug(1, "Already in a fax extension, not redirecting\n");
+ } else
+ ast_debug(1, "Fax already handled\n");
+ zt_confmute(p, 0);
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ *dest = &p->subs[index].f;
+ } else if (f->subclass == 'm') {
+ /* Confmute request */
+ zt_confmute(p, 1);
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ *dest = &p->subs[index].f;
+ } else if (f->subclass == 'u') {
+ /* Unmute */
+ zt_confmute(p, 0);
+ p->subs[index].f.frametype = AST_FRAME_NULL;
+ p->subs[index].f.subclass = 0;
+ *dest = &p->subs[index].f;
+ } else
+ zt_confmute(p, 0);
+}
static struct ast_frame *zt_handle_event(struct ast_channel *ast)
{
char *c;
struct zt_pvt *p = ast->tech_pvt;
pthread_t threadid;
- pthread_attr_t attr;
struct ast_channel *chan;
-
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+ struct ast_frame *f;
index = zt_get_index(ast, p, 0);
mysig = p->sig;
p->subs[index].f.offset = 0;
p->subs[index].f.src = "zt_handle_event";
p->subs[index].f.data = NULL;
+ f = &p->subs[index].f;
+
if (index < 0)
return &p->subs[index].f;
if (p->fake_event) {
} else
res = zt_get_event(p->subs[index].zfd);
- if (option_debug)
- ast_log(LOG_DEBUG, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
+ ast_debug(1, "Got event %s(%d) on channel %d (index %d)\n", event2str(res), res, p->channel, index);
if (res & (ZT_EVENT_PULSEDIGIT | ZT_EVENT_DTMFUP)) {
p->pulsedial = (res & ZT_EVENT_PULSEDIGIT) ? 1 : 0;
- if (option_debug)
- ast_log(LOG_DEBUG, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
+ ast_debug(1, "Detected %sdigit '%c'\n", p->pulsedial ? "pulse ": "", res & 0xff);
#ifdef HAVE_PRI
- if (!p->proceeding && p->sig == SIG_PRI && p->pri && p->pri->overlapdial) {
+ if (!p->proceeding && p->sig == SIG_PRI && p->pri && (p->pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING)) {
/* absorb event */
} else {
#endif
#ifdef HAVE_PRI
}
#endif
- /* Unmute conference, return the captured digit */
- zt_confmute(p, 0);
- return &p->subs[index].f;
+ zt_handle_dtmfup(ast, index, &f);
+ return f;
}
if (res & ZT_EVENT_DTMFDOWN) {
- if (option_debug)
- ast_log(LOG_DEBUG, "DTMF Down '%c'\n", res & 0xff);
+ ast_debug(1, "DTMF Down '%c'\n", res & 0xff);
/* Mute conference */
zt_confmute(p, 1);
p->subs[index].f.frametype = AST_FRAME_DTMF_BEGIN;
if (p->inalarm) break;
if ((p->radio || (p->oprmode < 0))) break;
if (ioctl(p->subs[index].zfd,ZT_DIALING,&x) == -1) {
- if (option_debug)
- ast_log(LOG_DEBUG, "ZT_DIALING ioctl failed on %s\n",ast->name);
+ ast_debug(1, "ZT_DIALING ioctl failed on %s\n",ast->name);
return NULL;
}
if (!x) { /* if not still dialing in driver */
}
if (ast->_state == AST_STATE_DIALING) {
if ((p->callprogress & 1) && CANPROGRESSDETECT(p) && p->dsp && p->outgoing) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Done dialing, but waiting for progress detection before doing more...\n");
+ ast_debug(1, "Done dialing, but waiting for progress detection before doing more...\n");
} else if (p->confirmanswer || (!p->dialednone && ((mysig == SIG_EM) || (mysig == SIG_EM_E1) || (mysig == SIG_EMWINK) || (mysig == SIG_FEATD) || (mysig == SIG_FEATDMF_TA) || (mysig == SIG_FEATDMF) || (mysig == SIG_E911) || (mysig == SIG_FGC_CAMA) || (mysig == SIG_FGC_CAMAMF) || (mysig == SIG_FEATB) || (mysig == SIG_SF) || (mysig == SIG_SFWINK) || (mysig == SIG_SF_FEATD) || (mysig == SIG_SF_FEATDMF) || (mysig == SIG_SF_FEATB)))) {
ast_setstate(ast, AST_STATE_RINGING);
} else if (!p->answeronpolarityswitch) {
return NULL;
}
mssinceflash = ast_tvdiff_ms(ast_tvnow(), p->flashtime);
- if (option_debug)
- ast_log(LOG_DEBUG, "Last flash was %d ms ago\n", mssinceflash);
+ ast_debug(1, "Last flash was %d ms ago\n", mssinceflash);
if (mssinceflash < MIN_MS_SINCE_FLASH) {
/* It hasn't been long enough since the last flashook. This is probably a bounce on
hanging up. Hangup both channels now */
if (p->subs[SUB_THREEWAY].owner)
ast_queue_hangup(p->subs[SUB_THREEWAY].owner);
p->subs[SUB_THREEWAY].owner->_softhangup |= AST_SOFTHANGUP_DEV;
- if (option_debug)
- ast_log(LOG_DEBUG, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
+ ast_debug(1, "Looks like a bounced flash, hanging up both calls on %d\n", p->channel);
ast_mutex_unlock(&p->subs[SUB_THREEWAY].owner->lock);
} else if ((ast->pbx) || (ast->_state == AST_STATE_UP)) {
if (p->transfer) {
p->subs[index].f.subclass = AST_CONTROL_ANSWER;
/* Make sure it stops ringing */
zt_set_hook(p->subs[index].zfd, ZT_OFFHOOK);
- if (option_debug)
- ast_log(LOG_DEBUG, "channel %d answered\n", p->channel);
+ ast_debug(1, "channel %d answered\n", p->channel);
if (p->cidspill) {
/* Cancel any running CallerID spill */
- free(p->cidspill);
+ ast_free(p->cidspill);
p->cidspill = NULL;
}
p->dialing = 0;
p->dop.dialstr[0] = '\0';
return NULL;
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
+ ast_debug(1, "Sent FXO deferred digit string: %s\n", p->dop.dialstr);
p->subs[index].f.frametype = AST_FRAME_NULL;
p->subs[index].f.subclass = 0;
p->dialing = 1;
ast->rings = 1;
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_OFFHOOK;
- if (option_debug)
- ast_log(LOG_DEBUG, "channel %d picked up\n", p->channel);
+ ast_debug(1, "channel %d picked up\n", p->channel);
return &p->subs[index].f;
case AST_STATE_UP:
/* Make sure it stops ringing */
/* If we get a ring then we cannot be in
* reversed polarity. So we reset to idle */
- if (option_debug)
- ast_log(LOG_DEBUG, "Setting IDLE polarity due "
- "to ring. Old polarity was %d\n",
- p->polarity);
+ ast_debug(1, "Setting IDLE polarity due "
+ "to ring. Old polarity was %d\n",
+ p->polarity);
p->polarity = POLARITY_IDLE;
/* Fall through */
if (ast->_state == AST_STATE_PRERING)
ast_setstate(ast, AST_STATE_RING);
if ((ast->_state == AST_STATE_DOWN) || (ast->_state == AST_STATE_RING)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Ring detected\n");
+ ast_debug(1, "Ring detected\n");
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_RING;
} else if (p->outgoing && ((ast->_state == AST_STATE_RINGING) || (ast->_state == AST_STATE_DIALING))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Line answered\n");
+ ast_debug(1, "Line answered\n");
if (p->confirmanswer) {
p->subs[index].f.frametype = AST_FRAME_NULL;
p->subs[index].f.subclass = 0;
ast->rings++;
if ((ast->rings > p->cidrings) && (p->cidspill)) {
ast_log(LOG_WARNING, "Didn't finish Caller-ID spill. Cancelling.\n");
- free(p->cidspill);
+ ast_free(p->cidspill);
p->cidspill = NULL;
p->callwaitcas = 0;
}
break;
}
/* Remember last time we got a flash-hook */
- gettimeofday(&p->flashtime, NULL);
+ p->flashtime = ast_tvnow();
switch (mysig) {
case SIG_FXOLS:
case SIG_FXOGS:
case SIG_FXOKS:
- if (option_debug)
- ast_log(LOG_DEBUG, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
- index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
+ ast_debug(1, "Winkflash, index: %d, normal: %d, callwait: %d, thirdcall: %d\n",
+ index, p->subs[SUB_REAL].zfd, p->subs[SUB_CALLWAIT].zfd, p->subs[SUB_THREEWAY].zfd);
p->callwaitcas = 0;
if (index != SUB_REAL) {
swap_subs(p, SUB_REAL, SUB_CALLWAIT);
tone_zone_play_tone(p->subs[SUB_REAL].zfd, -1);
p->owner = p->subs[SUB_REAL].owner;
- if (option_debug)
- ast_log(LOG_DEBUG, "Making %s the new owner\n", p->owner->name);
+ ast_debug(1, "Making %s the new owner\n", p->owner->name);
if (p->owner->_state == AST_STATE_RINGING) {
ast_setstate(p->owner, AST_STATE_UP);
p->subs[SUB_REAL].needanswer = 1;
if (!((ast->pbx) ||
(ast->_state == AST_STATE_UP) ||
(ast->_state == AST_STATE_RING))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Flash when call not up or ringing\n");
+ ast_debug(1, "Flash when call not up or ringing\n");
goto winkflashdone;
}
if (alloc_sub(p, SUB_THREEWAY)) {
p->owner = chan;
if (!chan) {
ast_log(LOG_WARNING, "Cannot allocate new structure on channel %d\n", p->channel);
- } else if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
+ } else if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
zt_enable_ec(p);
!ast_strlen_zero(p->mohsuggest) ? strlen(p->mohsuggest) + 1 : 0);
}
p->subs[SUB_THREEWAY].needhold = 1;
- }
+ }
}
} else {
/* Already have a 3 way call */
if (p->subs[SUB_THREEWAY].inthreeway) {
/* Call is already up, drop the last person */
- if (option_debug)
- ast_log(LOG_DEBUG, "Got flash with three way call up, dropping last call on %d\n", p->channel);
+ ast_debug(1, "Got flash with three way call up, dropping last call on %d\n", p->channel);
/* If the primary call isn't answered yet, use it */
if ((p->subs[SUB_REAL].owner->_state != AST_STATE_UP) && (p->subs[SUB_THREEWAY].owner->_state == AST_STATE_UP)) {
/* Swap back -- we're dropping the real 3-way that isn't finished yet*/
p->subs[otherindex].needunhold = 1;
p->owner = p->subs[SUB_REAL].owner;
if (ast->_state == AST_STATE_RINGING) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Enabling ringtone on real and threeway\n");
+ ast_debug(1, "Enabling ringtone on real and threeway\n");
res = tone_zone_play_tone(p->subs[SUB_REAL].zfd, ZT_TONE_RINGTONE);
res = tone_zone_play_tone(p->subs[SUB_THREEWAY].zfd, ZT_TONE_RINGTONE);
}
case SIG_FXSGS:
if (option_debug) {
if (p->dialing)
- ast_log(LOG_DEBUG, "Ignoring wink on channel %d\n", p->channel);
+ ast_debug(1, "Ignoring wink on channel %d\n", p->channel);
else
- ast_log(LOG_DEBUG, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
+ ast_debug(1, "Got wink in weird state %d on channel %d\n", ast->_state, p->channel);
}
break;
case SIG_FEATDMF_TA:
switch (p->whichwink) {
case 0:
- if (option_debug)
- ast_log(LOG_DEBUG, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
+ ast_debug(1, "ANI2 set to '%d' and ANI is '%s'\n", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
snprintf(p->dop.dialstr, sizeof(p->dop.dialstr), "M*%d%s#", p->owner->cid.cid_ani2, p->owner->cid.cid_ani);
break;
case 1:
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
p->dop.dialstr[0] = '\0';
return NULL;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
- }
+ } else
+ ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
+
p->dop.dialstr[0] = '\0';
break;
default:
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
p->dop.dialstr[0] = '\0';
return NULL;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", p->dop.dialstr);
- }
+ } else
+ ast_debug(1, "Sent deferred digit string: %s\n", p->dop.dialstr);
+
p->dop.dialstr[0] = '\0';
p->dop.op = ZT_DIAL_OP_REPLACE;
break;
case SIG_FEATB:
case SIG_SF_FEATDMF:
case SIG_SF_FEATB:
- if (option_debug)
- ast_log(LOG_DEBUG, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
+ ast_debug(1, "Got hook complete in MF FGD, waiting for wink now on channel %d\n",p->channel);
break;
default:
break;
if (p->answeronpolarityswitch &&
((ast->_state == AST_STATE_DIALING) ||
(ast->_state == AST_STATE_RINGING))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Answering on polarity switch!\n");
+ ast_debug(1, "Answering on polarity switch!\n");
ast_setstate(p->owner, AST_STATE_UP);
if (p->hanguponpolarityswitch) {
- gettimeofday(&p->polaritydelaytv, NULL);
+ p->polaritydelaytv = ast_tvnow();
}
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
- }
+ } else
+ ast_debug(1, "Ignore switch to REVERSED Polarity on channel %d, state %d\n", p->channel, ast->_state);
+
}
/* Removed else statement from here as it was preventing hangups from ever happening*/
/* Added AST_STATE_RING in if statement below to deal with calling party hangups that take place when ringing */
(p->polarity == POLARITY_REV) &&
((ast->_state == AST_STATE_UP) || (ast->_state == AST_STATE_RING)) ) {
/* Added log_debug information below to provide a better indication of what is going on */
- if (option_debug)
- ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
+ ast_debug(1, "Polarity Reversal event occured - DEBUG 1: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
if (ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) > p->polarityonanswerdelay) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
+ ast_debug(1, "Polarity Reversal detected and now Hanging up on channel %d\n", p->channel);
ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
p->polarity = POLARITY_IDLE;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
- }
+ } else
+ ast_debug(1, "Polarity Reversal detected but NOT hanging up (too close to answer event) on channel %d, state %d\n", p->channel, ast->_state);
+
} else {
p->polarity = POLARITY_IDLE;
- if (option_debug)
- ast_log(LOG_DEBUG, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
+ ast_debug(1, "Ignoring Polarity switch to IDLE on channel %d, state %d\n", p->channel, ast->_state);
}
/* Added more log_debug information below to provide a better indication of what is going on */
- if (option_debug)
- ast_log(LOG_DEBUG, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
+ ast_debug(1, "Polarity Reversal event occured - DEBUG 2: channel %d, state %d, pol= %d, aonp= %d, honp= %d, pdelay= %d, tv= %d\n", p->channel, ast->_state, p->polarity, p->answeronpolarityswitch, p->hanguponpolarityswitch, p->polarityonanswerdelay, ast_tvdiff_ms(ast_tvnow(), p->polaritydelaytv) );
break;
default:
- if (option_debug)
- ast_log(LOG_DEBUG, "Dunno what to do with event %d on channel %d\n", res, p->channel);
+ ast_debug(1, "Dunno what to do with event %d on channel %d\n", res, p->channel);
}
return &p->subs[index].f;
}
/* Switch to real if there is one and this isn't something really silly... */
if ((res != ZT_EVENT_RINGEROFF) && (res != ZT_EVENT_RINGERON) &&
(res != ZT_EVENT_HOOKCOMPLETE)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Restoring owner of channel %d on event %d\n", p->channel, res);
+ ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
p->owner = p->subs[SUB_REAL].owner;
if (p->owner && ast_bridged_channel(p->owner))
ast_queue_control(p->owner, AST_CONTROL_UNHOLD);
/* Do nothing */
break;
case ZT_EVENT_WINKFLASH:
- gettimeofday(&p->flashtime, NULL);
+ p->flashtime = ast_tvnow();
if (p->owner) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %d flashed to other channel %s\n", p->channel, p->owner->name);
f = &p->subs[index].f;
return f;
}
- if (!(p->radio || (p->oprmode < 0))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
- }
+ if (!(p->radio || (p->oprmode < 0)))
+ ast_debug(1, "Exception on %d, channel %d\n", ast->fds[0],p->channel);
/* If it's not us, return NULL immediately */
if (ast != p->owner) {
ast_log(LOG_WARNING, "We're %s, not %s\n", ast->name, p->owner->name);
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_HOLD;
ast_mutex_unlock(&p->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "Sending hold on '%s'\n", ast->name);
+ ast_debug(1, "Sending hold on '%s'\n", ast->name);
return &p->subs[index].f;
}
p->subs[index].f.frametype = AST_FRAME_CONTROL;
p->subs[index].f.subclass = AST_CONTROL_UNHOLD;
ast_mutex_unlock(&p->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "Sending unhold on '%s'\n", ast->name);
+ ast_debug(1, "Sending unhold on '%s'\n", ast->name);
return &p->subs[index].f;
}
return f;
}
if (res != (p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
+ ast_debug(1, "Short read (%d/%d), must be an event...\n", res, p->subs[index].linear ? READ_SIZE * 2 : READ_SIZE);
f = __zt_exception(ast);
ast_mutex_unlock(&p->lock);
return f;
c = tdd_feed(p->tdd,readbuf,READ_SIZE);
if (c < 0) {
- if (option_debug)
- ast_log(LOG_DEBUG,"tdd_feed failed\n");
+ ast_debug(1,"tdd_feed failed\n");
ast_mutex_unlock(&p->lock);
return NULL;
}
p->subs[index].f.offset = AST_FRIENDLY_OFFSET;
p->subs[index].f.data = p->subs[index].buffer + AST_FRIENDLY_OFFSET / sizeof(p->subs[index].buffer[0]);
#if 0
- if (option_debug)
- ast_log(LOG_DEBUG, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
+ ast_debug(1, "Read %d of voice on %s\n", p->subs[index].f.datalen, ast->name);
#endif
if (p->dialing || /* Transmitting something */
(index && (ast->_state != AST_STATE_UP)) || /* Three-way or callwait that isn't up */
}
} else if (f->frametype == AST_FRAME_DTMF) {
#ifdef HAVE_PRI
- if (!p->proceeding && p->sig==SIG_PRI && p->pri && p->pri->overlapdial) {
+ if (!p->proceeding && p->sig==SIG_PRI && p->pri &&
+ ((!p->outgoing && (p->pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING)) ||
+ (p->outgoing && (p->pri->overlapdial & ZAP_OVERLAPDIAL_OUTGOING)))) {
/* Don't accept in-band DTMF when in overlap dial mode */
f->frametype = AST_FRAME_NULL;
f->subclass = 0;
}
} else
f = &p->subs[index].f;
- if (f && (f->frametype == AST_FRAME_DTMF)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "DTMF digit: %c on %s\n", f->subclass, ast->name);
- if (p->confirmanswer) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Confirm answer on %s!\n", ast->name);
- /* Upon receiving a DTMF digit, consider this an answer confirmation instead
- of a DTMF digit */
- p->subs[index].f.frametype = AST_FRAME_CONTROL;
- p->subs[index].f.subclass = AST_CONTROL_ANSWER;
- f = &p->subs[index].f;
- /* Reset confirmanswer so DTMF's will behave properly for the duration of the call */
- p->confirmanswer = 0;
- } else if (p->callwaitcas) {
- if ((f->subclass == 'A') || (f->subclass == 'D')) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Got some DTMF, but it's for the CAS\n");
- if (p->cidspill)
- free(p->cidspill);
- send_cwcidspill(p);
- }
- if ((f->subclass != 'm') && (f->subclass != 'u'))
- p->callwaitcas = 0;
- p->subs[index].f.frametype = AST_FRAME_NULL;
- p->subs[index].f.subclass = 0;
- f = &p->subs[index].f;
- } else if (f->subclass == 'f') {
- /* Fax tone -- Handle and return NULL */
- if (!p->faxhandled) {
- p->faxhandled++;
- if (strcmp(ast->exten, "fax")) {
- const char *target_context = S_OR(ast->macrocontext, ast->context);
-
- if (ast_exists_extension(ast, target_context, "fax", 1, ast->cid.cid_num)) {
- if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Redirecting %s to fax extension\n", ast->name);
- /* Save the DID/DNIS when we transfer the fax call to a "fax" extension */
- pbx_builtin_setvar_helper(ast, "FAXEXTEN", ast->exten);
- if (ast_async_goto(ast, target_context, "fax", 1))
- ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast->name, target_context);
- } else
- ast_log(LOG_NOTICE, "Fax detected, but no fax extension\n");
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Already in a fax extension, not redirecting\n");
- }
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Fax already handled\n");
- }
- zt_confmute(p, 0);
- p->subs[index].f.frametype = AST_FRAME_NULL;
- p->subs[index].f.subclass = 0;
- f = &p->subs[index].f;
- } else if (f->subclass == 'm') {
- /* Confmute request */
- zt_confmute(p, 1);
- p->subs[index].f.frametype = AST_FRAME_NULL;
- p->subs[index].f.subclass = 0;
- f = &p->subs[index].f;
- } else if (f->subclass == 'u') {
- /* Unmute */
- zt_confmute(p, 0);
- p->subs[index].f.frametype = AST_FRAME_NULL;
- p->subs[index].f.subclass = 0;
- f = &p->subs[index].f;
- } else
- zt_confmute(p, 0);
- }
+
+ if (f && (f->frametype == AST_FRAME_DTMF))
+ zt_handle_dtmfup(ast, index, &f);
/* If we have a fake_event, trigger exception to handle it */
if (p->fake_event)
size = (linear ? READ_SIZE * 2 : READ_SIZE);
res = write(fd, buf, size);
if (res != size) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
+ ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
return sent;
}
len -= size;
return -1;
}
if (p->dialing) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Dropping frame since I'm still dialing on %s...\n",ast->name);
+ ast_debug(1, "Dropping frame since I'm still dialing on %s...\n",ast->name);
return 0;
}
if (!p->owner) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Dropping frame since there is no active owner on %s...\n",ast->name);
+ ast_debug(1, "Dropping frame since there is no active owner on %s...\n",ast->name);
return 0;
}
if (p->cidspill) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Dropping frame since I've still got a callerid spill\n");
+ ast_debug(1, "Dropping frame since I've still got a callerid spill\n");
return 0;
}
/* Return if it's not valid data */
int func = ZT_FLASH;
ast_mutex_lock(&p->lock);
index = zt_get_index(chan, p, 0);
- if (option_debug)
- ast_log(LOG_DEBUG, "Requested indication %d on channel %s\n", condition, chan->name);
+ ast_debug(1, "Requested indication %d on channel %s\n", condition, chan->name);
if (index == SUB_REAL) {
switch (condition) {
case AST_CONTROL_BUSY:
}
break;
case AST_CONTROL_PROCEEDING:
- if (option_debug)
- ast_log(LOG_DEBUG,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
+ ast_debug(1,"Received AST_CONTROL_PROCEEDING on %s\n",chan->name);
#ifdef HAVE_PRI
if (!p->proceeding && p->sig==SIG_PRI && p->pri && !p->outgoing) {
if (p->pri->pri) {
res = 0;
break;
case AST_CONTROL_PROGRESS:
- if (option_debug)
- ast_log(LOG_DEBUG,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
+ ast_debug(1,"Received AST_CONTROL_PROGRESS on %s\n",chan->name);
#ifdef HAVE_PRI
p->digital = 0; /* Digital-only calls isn't allows any inband progress messages */
if (!p->progress && p->sig==SIG_PRI && p->pri && !p->outgoing) {
int res;
int x,y;
int features;
- char *b2 = 0;
+ struct ast_str *chan_name;
ZT_PARAMS ps;
if (i->subs[index].owner) {
ast_log(LOG_WARNING, "Channel %d already has a %s call\n", i->channel,subnames[index]);
return NULL;
}
y = 1;
+ chan_name = ast_str_alloca(32);
do {
- if (b2)
- free(b2);
#ifdef HAVE_PRI
if (i->bearer || (i->pri && (i->sig == SIG_FXSKS)))
- asprintf(&b2, "Zap/%d:%d-%d", i->pri->trunkgroup, i->channel, y);
+ ast_str_set(&chan_name, 0, "%d:%d-%d", i->pri->trunkgroup, i->channel, y);
else
#endif
if (i->channel == CHAN_PSEUDO)
- asprintf(&b2, "Zap/pseudo-%ld", ast_random());
+ ast_str_set(&chan_name, 0, "pseudo-%ld", ast_random());
else
- asprintf(&b2, "Zap/%d-%d", i->channel, y);
+ ast_str_set(&chan_name, 0, "%d-%d", i->channel, y);
for (x = 0; x < 3; x++) {
- if ((index != x) && i->subs[x].owner && !strcasecmp(b2, i->subs[x].owner->name))
+ if ((index != x) && i->subs[x].owner && !strcasecmp(chan_name->str, i->subs[x].owner->name))
break;
}
y++;
} while (x < 3);
- tmp = ast_channel_alloc(0, state, 0, 0, b2);
- if (b2) /*!> b2 can be freed now, it's been copied into the channel structure */
- free(b2);
+ tmp = ast_channel_alloc(0, state, i->cid_num, i->cid_name, i->accountcode, i->exten, i->context, i->amaflags, "Zap/%s", chan_name->str);
if (!tmp)
return NULL;
tmp->tech = &zap_tech;
i->subs[index].linear = 0;
zt_setlinear(i->subs[index].zfd, i->subs[index].linear);
features = 0;
- if (i->busydetect && CANBUSYDETECT(i))
- features |= DSP_FEATURE_BUSY_DETECT;
- if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
- features |= DSP_FEATURE_CALL_PROGRESS;
- if ((!i->outgoing && (i->callprogress & 4)) ||
- (i->outgoing && (i->callprogress & 2))) {
- features |= DSP_FEATURE_FAX_DETECT;
- }
+ if (index == SUB_REAL) {
+ if (i->busydetect && CANBUSYDETECT(i))
+ features |= DSP_FEATURE_BUSY_DETECT;
+ if ((i->callprogress & 1) && CANPROGRESSDETECT(i))
+ features |= DSP_FEATURE_CALL_PROGRESS;
+ if ((!i->outgoing && (i->callprogress & 4)) ||
+ (i->outgoing && (i->callprogress & 2))) {
+ features |= DSP_FEATURE_FAX_DETECT;
+ }
#ifdef ZT_TONEDETECT
- x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
- if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
+ x = ZT_TONEDETECT_ON | ZT_TONEDETECT_MUTE;
+ if (ioctl(i->subs[index].zfd, ZT_TONEDETECT, &x)) {
#endif
- i->hardwaredtmf = 0;
- features |= DSP_FEATURE_DTMF_DETECT;
+ i->hardwaredtmf = 0;
+ features |= DSP_FEATURE_DTMF_DETECT;
#ifdef ZT_TONEDETECT
- } else if (NEED_MFDETECT(i)) {
- i->hardwaredtmf = 1;
- features |= DSP_FEATURE_DTMF_DETECT;
- }
+ } else if (NEED_MFDETECT(i)) {
+ i->hardwaredtmf = 1;
+ features |= DSP_FEATURE_DTMF_DETECT;
+ }
#endif
+ }
if (features) {
if (i->dsp) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Already have a dsp on %s?\n", tmp->name);
+ ast_debug(1, "Already have a dsp on %s?\n", tmp->name);
} else {
if (i->channel != CHAN_PSEUDO)
i->dsp = ast_dsp_new();
tmp->cid.cid_num = ast_strdup(i->cid_num);
tmp->cid.cid_name = ast_strdup(i->cid_name);
if (!ast_strlen_zero(i->cid_ani))
- tmp->cid.cid_ani = ast_strdup(i->cid_num);
+ tmp->cid.cid_ani = ast_strdup(i->cid_ani);
else
tmp->cid.cid_ani = ast_strdup(i->cid_num);
#else
}
}
+ ast_module_ref(ast_module_info->self);
return tmp;
}
int res;
int index;
+ /* in the bizarre case where the channel has become a zombie before we
+ even get started here, abort safely
+ */
+ if (!p) {
+ ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
+ ast_hangup(chan);
+ return NULL;
+ }
+
if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s'\n", chan->name);
index = zt_get_index(chan, p, 1);
timeout = gendigittimeout;
res = ast_waitfordigit(chan, timeout);
if (res < 0) {
- if (option_debug)
- ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
+ ast_debug(1, "waitfordigit returned < 0...\n");
ast_hangup(chan);
return NULL;
} else if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero!\n");
}
} else {
- if (option_debug)
- ast_log(LOG_DEBUG, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
+ ast_debug(1, "No such possible extension '%s' in context '%s'\n", exten, chan->context);
chan->hangupcause = AST_CAUSE_UNALLOCATED;
ast_hangup(chan);
p->exten[0] = '\0';
}
res = ast_waitfordigit(chan, timeout);
if (res < 0) {
- if (option_debug)
- ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
+ ast_debug(1, "waitfordigit returned < 0...\n");
ast_hangup(chan);
return NULL;
} else if (res) {
ast_hangup(chan);
return NULL;
} else if (res < 0) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Got hung up before digits finished\n");
+ ast_debug(1, "Got hung up before digits finished\n");
ast_hangup(chan);
return NULL;
}
res = ast_waitfordigit(chan, timeout);
timeout = 0;
if (res < 0) {
- if (option_debug)
- ast_log(LOG_DEBUG, "waitfordigit returned < 0...\n");
+ ast_debug(1, "waitfordigit returned < 0...\n");
res = tone_zone_play_tone(p->subs[index].zfd, -1);
ast_hangup(chan);
return NULL;
timeout = matchdigittimeout;
}
} else if (res == 0) {
- if (option_debug)
- ast_log(LOG_DEBUG, "not enough digits (and no ambiguous match)...\n");
+ ast_debug(1, "not enough digits (and no ambiguous match)...\n");
res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
zt_wait_event(p->subs[index].zfd);
ast_hangup(chan);
}
zt_enable_ec(p);
if (ast_pickup_call(chan)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "No call pickup possible...\n");
+ ast_debug(1, "No call pickup possible...\n");
res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_CONGESTION);
zt_wait_event(p->subs[index].zfd);
}
/* Disable Caller*ID if enabled */
p->hidecallerid = 1;
if (chan->cid.cid_num)
- free(chan->cid.cid_num);
+ ast_free(chan->cid.cid_num);
chan->cid.cid_num = NULL;
if (chan->cid.cid_name)
- free(chan->cid.cid_name);
+ ast_free(chan->cid.cid_name);
chan->cid.cid_name = NULL;
res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
if (res) {
/* Enable Caller*ID if enabled */
p->hidecallerid = 0;
if (chan->cid.cid_num)
- free(chan->cid.cid_num);
+ ast_free(chan->cid.cid_num);
chan->cid.cid_num = NULL;
if (chan->cid.cid_name)
- free(chan->cid.cid_name);
+ ast_free(chan->cid.cid_name);
chan->cid.cid_name = NULL;
ast_set_callerid(chan, p->cid_num, p->cid_name, NULL);
res = tone_zone_play_tone(p->subs[index].zfd, ZT_TONE_DIALRECALL);
}
} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
((exten[0] != '*') || (strlen(exten) > 2))) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
+ ast_debug(1, "Can't match %s from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
break;
}
if (!timeout)
res = 0;
ast_frfree(f);
if (res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Got ring!\n");
+ ast_debug(1, "Got ring!\n");
res = 0;
break;
}
else if (smdi_msg->type == 'N')
pbx_builtin_setvar_helper(chan, "_SMDI_VM_TYPE", "u");
- if (option_debug)
- ast_log(LOG_DEBUG, "Recieved SMDI message on %s\n", chan->name);
+ ast_debug(1, "Recieved SMDI message on %s\n", chan->name);
} else {
ast_log(LOG_WARNING, "SMDI enabled but no SMDI message present\n");
}
/* If we want caller id, we're in a prering state due to a polarity reversal
* and we're set to use a polarity reversal to trigger the start of caller id,
* grab the caller id and wait for ringing to start... */
- } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && p->cid_start == CID_START_POLARITY)) {
+ } else if (p->use_callerid && (chan->_state == AST_STATE_PRERING && (p->cid_start == CID_START_POLARITY || p->cid_start == CID_START_POLARITY_IN))) {
/* If set to use DTMF CID signalling, listen for DTMF */
if (p->cid_signalling == CID_SIG_DTMF) {
int i = 0;
cs = NULL;
- if (option_debug)
- ast_log(LOG_DEBUG, "Receiving DTMF cid on "
- "channel %s\n", chan->name);
+ ast_debug(1, "Receiving DTMF cid on "
+ "channel %s\n", chan->name);
zt_setlinear(p->subs[index].zfd, 0);
res = 2000;
for (;;) {
f = ast_read(chan);
if (f->frametype == AST_FRAME_DTMF) {
dtmfbuf[i++] = f->subclass;
- if (option_debug)
- ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
+ ast_debug(1, "CID got digit '%c'\n", f->subclass);
res = 2000;
}
ast_frfree(f);
dtmfbuf[i] = '\0';
zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
/* Got cid and ring. */
- if (option_debug)
- ast_log(LOG_DEBUG, "CID got string '%s'\n", dtmfbuf);
+ ast_debug(1, "CID got string '%s'\n", dtmfbuf);
callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
- if (option_debug)
- ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
- dtmfcid, flags);
+ ast_debug(1, "CID is '%s', flags %d\n",
+ dtmfcid, flags);
/* If first byte is NULL, we have no cid */
if (!ast_strlen_zero(dtmfcid))
number = dtmfcid;
return NULL;
}
} else if (p->use_callerid && p->cid_start == CID_START_RING) {
+ if (p->cid_signalling == CID_SIG_DTMF) {
+ int i = 0;
+ cs = NULL;
+ zt_setlinear(p->subs[index].zfd, 0);
+ res = 2000;
+ for (;;) {
+ struct ast_frame *f;
+ res = ast_waitfor(chan, res);
+ if (res <= 0) {
+ ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
+ "Exiting simple switch\n");
+ ast_hangup(chan);
+ return NULL;
+ }
+ f = ast_read(chan);
+ if (f->frametype == AST_FRAME_DTMF) {
+ dtmfbuf[i++] = f->subclass;
+ ast_log(LOG_DEBUG, "CID got digit '%c'\n", f->subclass);
+ res = 2000;
+ }
+ ast_frfree(f);
+
+ if (p->ringt_base == p->ringt)
+ break;
+
+ }
+ dtmfbuf[i] = '\0';
+ zt_setlinear(p->subs[index].zfd, p->subs[index].linear);
+ /* Got cid and ring. */
+ callerid_get_dtmf(dtmfbuf, dtmfcid, &flags);
+ ast_log(LOG_DEBUG, "CID is '%s', flags %d\n",
+ dtmfcid, flags);
+ /* If first byte is NULL, we have no cid */
+ if (!ast_strlen_zero(dtmfcid))
+ number = dtmfcid;
+ else
+ number = NULL;
+ /* If set to use V23 Signalling, launch our FSK gubbins and listen for it */
+ } else {
/* FSK Bell202 callerID */
cs = callerid_new(p->cid_signalling);
if (cs) {
}
if (res == 1) {
callerid_get(cs, &name, &number, &flags);
- if (option_debug)
- ast_log(LOG_DEBUG, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
+ ast_debug(1, "CallerID number: %s, name: %s, flags=%d\n", number, name, flags);
}
if (distinctiveringaftercid == 1) {
/* Clear the current ring data array so we dont have old data in it. */
} else
ast_log(LOG_WARNING, "Unable to get caller ID space\n");
}
+ }
else
cs = NULL;
return NULL;
}
+/* destroy a zaptel channel, identified by its number */
+static int zap_destroy_channel_bynum(int channel)
+{
+ struct zt_pvt *tmp = NULL;
+ struct zt_pvt *prev = NULL;
+
+ tmp = iflist;
+ while (tmp) {
+ if (tmp->channel == channel) {
+ destroy_channel(prev, tmp, 1);
+ return RESULT_SUCCESS;
+ }
+ prev = tmp;
+ tmp = tmp->next;
+ }
+ return RESULT_FAILURE;
+}
+
static int handle_init_event(struct zt_pvt *i, int event)
{
int res;
pthread_t threadid;
- pthread_attr_t attr;
struct ast_channel *chan;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
/* Handle an event on a given channel for the monitor thread. */
switch (event) {
case ZT_EVENT_NONE:
break;
if (i->cidspill) {
/* Cancel VMWI spill */
- free(i->cidspill);
+ ast_free(i->cidspill);
i->cidspill = NULL;
}
if (i->immediate) {
res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_DIALTONE);
if (res < 0)
ast_log(LOG_WARNING, "Unable to play dialtone on channel %d\n", i->channel);
- if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
+ if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
if (res < 0)
case SIG_SF_FEATB:
case SIG_SF:
/* Check for callerid, digits, etc */
- chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
- if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
+ if (i->cid_start == CID_START_POLARITY_IN) {
+ chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
+ } else {
+ chan = zt_new(i, AST_STATE_RING, 0, SUB_REAL, 0, 0);
+ }
+ if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
res = tone_zone_play_tone(i->subs[SUB_REAL].zfd, ZT_TONE_CONGESTION);
if (res < 0)
case SIG_FXSLS:
case SIG_FXSKS:
case SIG_FXSGS:
- if (i->cid_start == CID_START_POLARITY) {
+ if (i->cid_start == CID_START_POLARITY || i->cid_start == CID_START_POLARITY_IN) {
i->polarity = POLARITY_REV;
ast_verbose(VERBOSE_PREFIX_2 "Starting post polarity "
"CID detection on channel %d\n",
i->channel);
chan = zt_new(i, AST_STATE_PRERING, 0, SUB_REAL, 0, 0);
- if (chan && ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
+ if (chan && ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", i->channel);
}
}
"polarity reversal on non-FXO (SIG_FXS) "
"interface %d\n", i->channel);
}
+ break;
+ case ZT_EVENT_REMOVED: /* destroy channel */
+ ast_log(LOG_NOTICE,
+ "Got ZT_EVENT_REMOVED. Destroying channel %d\n",
+ i->channel);
+ zap_destroy_channel_bynum(i->channel);
+ break;
}
return 0;
}
ast_log(LOG_WARNING, "Unable to set cancel type to asynchronous\n");
return NULL;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Monitor starting...\n");
+ ast_debug(1, "Monitor starting...\n");
#endif
for (;;) {
/* Lock the interface list */
ast_mutex_lock(&iflock);
if (!pfds || (lastalloc != ifcount)) {
if (pfds)
- free(pfds);
+ ast_free(pfds);
if (ifcount) {
if (!(pfds = ast_calloc(1, ifcount * sizeof(*pfds)))) {
ast_mutex_unlock(&iflock);
if (last) {
if (!last->cidspill && !last->owner && !ast_strlen_zero(last->mailbox) && (thispass - last->onhooktime > 3) &&
(last->sig & __ZT_SIG_FXO)) {
- res = ast_app_has_voicemail(last->mailbox, NULL);
+ res = has_voicemail(last);
if (last->msgstate != res) {
int x;
- if (option_debug)
- ast_log(LOG_DEBUG, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
+ ast_debug(1, "Message status for %s changed from %d to %d on %d\n", last->mailbox, last->msgstate, res, last->channel);
x = ZT_FLUSH_BOTH;
res2 = ioctl(last->subs[SUB_REAL].zfd, ZT_FLUSH, &x);
if (res2)
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);
+ ast_debug(1, "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);
if (res2 > 0) {
i->cidpos += res2;
if (i->cidpos >= i->cidlen) {
- free(i->cidspill);
+ ast_free(i->cidspill);
i->cidspill = 0;
i->cidpos = 0;
i->cidlen = 0;
} else {
ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
+ ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events -- race with chlock */
ast_mutex_unlock(&iflock);
handle_init_event(i, res);
continue;
}
res = zt_get_event(i->subs[SUB_REAL].zfd);
- if (option_debug)
- ast_log(LOG_DEBUG, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
+ ast_debug(1, "Monitor doohicky got event %s on channel %d\n", event2str(res), i->channel);
/* Don't hold iflock while handling init events */
ast_mutex_unlock(&iflock);
handle_init_event(i, res);
static int restart_monitor(void)
{
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
/* If we're supposed to be stopped -- stay stopped */
if (monitor_thread == AST_PTHREADT_STOP)
return 0;
return -1;
}
if (monitor_thread != AST_PTHREADT_NULL) {
- /* Just signal it to be sure it wakes up */
-#if 0
- pthread_cancel(monitor_thread);
-#endif
+ /* Wake up the thread */
pthread_kill(monitor_thread, SIGURG);
-#if 0
- pthread_join(monitor_thread, NULL);
-#endif
} else {
/* Start a new monitor */
- if (ast_pthread_create_background(&monitor_thread, &attr, do_monitor, NULL) < 0) {
+ if (ast_pthread_create_detached_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
ast_mutex_unlock(&monlock);
ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
return -1;
unsigned int code1, code2, code3;
int numvals;
- numvals = sscanf(pcstring, "%d.%d.%d", &code1, &code2, &code3);
+ numvals = sscanf(pcstring, "%d-%d-%d", &code1, &code2, &code3);
if (numvals == 1)
return code1;
if (numvals == 3)
tmp->cic = cur_cicbeginswith++;
+ /* DB: Add CIC's DPC information */
+ tmp->dpc = cur_defaultdpc;
+
tmp->ss7 = ss7;
tmp->ss7call = NULL;
ss7->pvts[ss7->numchans++] = tmp;
+
+ ast_copy_string(linksets[span].internationalprefix, conf.ss7.internationalprefix, sizeof(linksets[span].internationalprefix));
+ ast_copy_string(linksets[span].nationalprefix, conf.ss7.nationalprefix, sizeof(linksets[span].nationalprefix));
+ ast_copy_string(linksets[span].subscriberprefix, conf.ss7.subscriberprefix, sizeof(linksets[span].subscriberprefix));
+ ast_copy_string(linksets[span].unknownprefix, conf.ss7.unknownprefix, sizeof(linksets[span].unknownprefix));
+
+ linksets[span].called_nai = conf.ss7.called_nai;
+ linksets[span].calling_nai = conf.ss7.calling_nai;
}
#endif
#ifdef HAVE_PRI
tmp->canpark = conf.chan.canpark;
tmp->transfer = conf.chan.transfer;
ast_copy_string(tmp->defcontext,conf.chan.context,sizeof(tmp->defcontext));
- ast_copy_string(tmp->language, language, sizeof(tmp->language));
+ ast_copy_string(tmp->language, conf.chan.language, sizeof(tmp->language));
ast_copy_string(tmp->mohinterpret, conf.chan.mohinterpret, sizeof(tmp->mohinterpret));
ast_copy_string(tmp->mohsuggest, conf.chan.mohsuggest, sizeof(tmp->mohsuggest));
ast_copy_string(tmp->context, conf.chan.context, sizeof(tmp->context));
tmp->cid_ton = 0;
ast_copy_string(tmp->cid_name, conf.chan.cid_name, sizeof(tmp->cid_name));
ast_copy_string(tmp->mailbox, conf.chan.mailbox, sizeof(tmp->mailbox));
+ if (!ast_strlen_zero(tmp->mailbox)) {
+ tmp->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, NULL,
+ AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, tmp->mailbox,
+ AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
+ AST_EVENT_IE_END);
+ }
tmp->msgstate = -1;
tmp->group = conf.chan.group;
tmp->callgroup = conf.chan.callgroup;
tmp->pickupgroup= conf.chan.pickupgroup;
+ tmp->cid_rxgain = conf.chan.cid_rxgain;
tmp->rxgain = conf.chan.rxgain;
tmp->txgain = conf.chan.txgain;
tmp->tonezone = conf.chan.tonezone;
return 1;
#endif
} else if (par.rxisoffhook) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Channel %d off hook, can't use\n", p->channel);
+ ast_debug(1, "Channel %d off hook, can't use\n", p->channel);
/* Not available when the other end is off hook */
return 0;
}
if (!backwards && (x >= pri->numchans))
break;
if (pri->pvts[x] && !pri->pvts[x]->inalarm && !pri->pvts[x]->owner) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Found empty available channel %d/%d\n",
- pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
+ ast_debug(1, "Found empty available channel %d/%d\n",
+ pri->pvts[x]->logicalspan, pri->pvts[x]->prioffset);
return x;
}
if (backwards)
#endif
if (p && available(p, channelmatch, groupmatch, &busy, &channelmatched, &groupmatched)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Using channel %d\n", p->channel);
- if (p->inalarm)
- goto next;
+ ast_debug(1, "Using channel %d\n", p->channel);
+ if (p->inalarm)
+ goto next;
callwait = (p->owner != NULL);
#ifdef HAVE_PRI
ast_log(LOG_NOTICE, "Failed to allocate place holder pseudo channel!\n");
p = NULL;
break;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Allocated placeholder pseudo channel\n");
- }
+ } else
+ ast_debug(1, "Allocated placeholder pseudo channel\n");
+
p->pri = pri;
}
}
static void ss7_reset_linkset(struct zt_ss7 *linkset)
{
- int i, startcic = -1, endcic;
+ int i, startcic = -1, endcic, dpc;
if (linkset->numchans <= 0)
return;
startcic = linkset->pvts[0]->cic;
+ /* DB: CIC's DPC fix */
+ dpc = linkset->pvts[0]->dpc;
for (i = 0; i < linkset->numchans; i++) {
- if (linkset->pvts[i+1] && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
+ if (linkset->pvts[i+1] && linkset->pvts[i+1]->dpc == dpc && ((linkset->pvts[i+1]->cic - linkset->pvts[i]->cic) == 1) && (linkset->pvts[i]->cic - startcic < 31)) {
continue;
} else {
endcic = linkset->pvts[i]->cic;
ast_verbose("Resetting CICs %d to %d\n", startcic, endcic);
- isup_grs(linkset->ss7, startcic, endcic);
+ isup_grs(linkset->ss7, startcic, endcic, dpc);
- if (linkset->pvts[i+1])
+ /* DB: CIC's DPC fix */
+ if (linkset->pvts[i+1]) {
startcic = linkset->pvts[i+1]->cic;
+ dpc = linkset->pvts[i+1]->dpc;
+ }
}
}
}
ast_log(LOG_WARNING, "Unable to start PBX on CIC %d\n", p->cic);
}
+static void ss7_apply_plan_to_number(char *buf, size_t size, const struct zt_ss7 *ss7, const char *number, const unsigned nai)
+{
+ switch (nai) {
+ case SS7_NAI_INTERNATIONAL:
+ snprintf(buf, size, "%s%s", ss7->internationalprefix, number);
+ break;
+ case SS7_NAI_NATIONAL:
+ snprintf(buf, size, "%s%s", ss7->nationalprefix, number);
+ break;
+ case SS7_NAI_SUBSCRIBER:
+ snprintf(buf, size, "%s%s", ss7->subscriberprefix, number);
+ break;
+ case SS7_NAI_UNKNOWN:
+ snprintf(buf, size, "%s%s", ss7->unknownprefix, number);
+ break;
+ default:
+ snprintf(buf, size, "%s", number);
+ break;
+ }
+}
+static int ss7_pres_scr2cid_pres(char presentation_ind, char screening_ind)
+{
+ return ((presentation_ind & 0x3) << 5) | (screening_ind & 0x3);
+}
+
static void *ss7_linkset(void *data)
{
int res, i;
ss7_event *e = NULL;
struct zt_pvt *p;
int chanpos;
- pthread_attr_t attr;
struct pollfd pollers[NUM_DCHANS];
int cic;
+ unsigned int dpc;
int nextms = 0;
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
ss7_start(ss7);
while(1) {
ast_mutex_lock(&linkset->lock);
if ((next = ss7_schedule_next(ss7))) {
- gettimeofday(&tv, NULL);
+ tv = ast_tvnow();
tv.tv_sec = next->tv_sec - tv.tv_sec;
tv.tv_usec = next->tv_usec - tv.tv_usec;
if (tv.tv_usec < 0) {
}
switch (x) {
case ZT_EVENT_OVERRUN:
- ast_log(LOG_DEBUG, "Overrun detected!\n");
+ ast_debug(1, "Overrun detected!\n");
break;
case ZT_EVENT_BADFCS:
- ast_log(LOG_DEBUG, "Bad FCS\n");
+ ast_debug(1, "Bad FCS\n");
break;
case ZT_EVENT_ABORT:
- ast_log(LOG_DEBUG, "HDLC Abort\n");
+ ast_debug(1, "HDLC Abort\n");
break;
case ZT_EVENT_ALARM:
ast_log(LOG_ERROR, "Alarm on link!\n");
while ((e = ss7_check_event(ss7))) {
switch (e->e) {
case SS7_EVENT_UP:
- ast_verbose("--- SS7 Up ---\n");
- if (linkset->state != LINKSET_STATE_UP)
+ if (linkset->state != LINKSET_STATE_UP) {
+ ast_verbose("--- SS7 Up ---\n");
ss7_reset_linkset(linkset);
+ }
linkset->state = LINKSET_STATE_UP;
break;
case SS7_EVENT_DOWN:
}
break;
case MTP2_LINK_UP:
- ast_log(LOG_DEBUG, "MTP2 link up\n");
+ ast_debug(1, "MTP2 link up\n");
break;
case ISUP_EVENT_CPG:
chanpos = ss7_find_cic(linkset, e->cpg.cic);
case CPG_EVENT_INBANDINFO:
{
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROGRESS, };
- ast_log(LOG_DEBUG, "Queuing frame PROGRESS on CIC %d\n", p->cic);
- zap_queue_frame(p, &f, ss7);
+ ast_debug(1, "Queuing frame PROGRESS on CIC %d\n", p->cic);
+ zap_queue_frame(p, &f, linkset);
p->progress = 1;
}
break;
default:
- ast_log(LOG_DEBUG, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
+ ast_debug(1, "Do not handle CPG with event type 0x%x\n", e->cpg.event);
}
ast_mutex_unlock(&p->lock);
ast_mutex_lock(&p->lock);
p->inservice = 1;
p->remotelyblocked = 0;
+ dpc = p->dpc;
+ isup_set_call_dpc(e->rsc.call, dpc);
ast_mutex_unlock(&p->lock);
isup_rlc(ss7, e->rsc.call);
break;
case ISUP_EVENT_GRS:
- ast_log(LOG_DEBUG, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
- isup_gra(ss7, e->grs.startcic, e->grs.endcic);
+ ast_debug(1, "Got Reset for CICs %d to %d: Acknowledging\n", e->grs.startcic, e->grs.endcic);
+ chanpos = ss7_find_cic(linkset, e->grs.startcic);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "GRS on unconfigured CIC %d\n", e->grs.startcic);
+ break;
+ }
+ p = linkset->pvts[chanpos];
+ isup_gra(ss7, e->grs.startcic, e->grs.endcic, p->dpc);
ss7_block_cics(linkset, e->grs.startcic, e->grs.endcic, NULL, 0);
break;
case ISUP_EVENT_GRA:
ss7_block_cics(linkset, e->gra.startcic, e->gra.endcic, e->gra.status, 1);
break;
case ISUP_EVENT_IAM:
- ast_log(LOG_DEBUG, "Got IAM for CIC %d and number %s\n", e->iam.cic, e->iam.called_party_num);
+ ast_debug(1, "Got IAM for CIC %d and called number %s, calling number %s\n", e->iam.cic, e->iam.called_party_num, e->iam.calling_party_num);
chanpos = ss7_find_cic(linkset, e->iam.cic);
if (chanpos < 0) {
ast_log(LOG_WARNING, "IAM on unconfigured CIC %d\n", e->iam.cic);
}
}
+ dpc = p->dpc;
p->ss7call = e->iam.call;
+ isup_set_call_dpc(p->ss7call, dpc);
- if (p->use_callerid)
- ast_copy_string(p->cid_num, e->iam.calling_party_num, sizeof(p->cid_num));
+ if ( (p->use_callerid) && (!ast_strlen_zero(e->iam.calling_party_num)) )
+ {
+ ss7_apply_plan_to_number(p->cid_num, sizeof(p->cid_num), linkset, e->iam.calling_party_num, e->iam.calling_nai);
+ p->callingpres = ss7_pres_scr2cid_pres(e->iam.presentation_ind, e->iam.screening_ind);
+ }
else
p->cid_num[0] = 0;
p->exten[1] = '\0';
} else if (!ast_strlen_zero(e->iam.called_party_num)) {
char *st;
- ast_copy_string(p->exten, e->iam.called_party_num, sizeof(p->exten));
+ ss7_apply_plan_to_number(p->exten, sizeof(p->exten), linkset, e->iam.called_party_num, e->iam.called_nai);
st = strchr(p->exten, '#');
if (st)
*st = '\0';
p->cid_ton = 0;
/* Set DNID */
if (!ast_strlen_zero(e->iam.called_party_num))
- ast_copy_string(p->dnid, e->iam.called_party_num, sizeof(p->exten));
-
+ ss7_apply_plan_to_number(p->dnid, sizeof(p->dnid), linkset, e->iam.called_party_num, e->iam.called_nai);
+
if (ast_exists_extension(NULL, p->context, p->exten, 1, p->cid_num)) {
if (e->iam.cot_check_required) {
} else
ss7_start_call(p, linkset);
} else {
- ast_log(LOG_DEBUG, "Call on CIC for unconfigured extension %s\n", p->exten);
+ ast_debug(1, "Call on CIC for unconfigured extension %s\n", p->exten);
isup_rel(ss7, e->iam.call, -1);
}
ast_mutex_unlock(&p->lock);
}
p = linkset->pvts[chanpos];
ast_mutex_lock(&p->lock);
- if (p->owner)
- ast_queue_hangup(p->owner);
- else
+ if (p->owner) {
+ p->owner->hangupcause = e->rel.cause;
+ p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ } else
ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
isup_rlc(ss7, e->rel.call);
p = linkset->pvts[chanpos];
- ast_log(LOG_DEBUG, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
+ ast_debug(1, "Queueing frame from SS7_EVENT_ACM on CIC %d\n", p->cic);
ast_mutex_lock(&p->lock);
zap_queue_frame(p, &f, linkset);
}
break;
case ISUP_EVENT_CGB:
+ chanpos = ss7_find_cic(linkset, e->cgb.startcic);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "CGB on unconfigured CIC %d\n", e->cgb.startcic);
+ break;
+ }
+ p = linkset->pvts[chanpos];
ss7_block_cics(linkset, e->cgb.startcic, e->cgb.endcic, e->cgb.status, 1);
- isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, e->cgb.status);
+ isup_cgba(linkset->ss7, e->cgb.startcic, e->cgb.endcic, p->dpc, e->cgb.status, e->cgb.type);
break;
case ISUP_EVENT_CGU:
- ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgb.status, 0);
- isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, e->cgb.status);
+ chanpos = ss7_find_cic(linkset, e->cgu.startcic);
+ if (chanpos < 0) {
+ ast_log(LOG_WARNING, "CGU on unconfigured CIC %d\n", e->cgu.startcic);
+ break;
+ }
+ p = linkset->pvts[chanpos];
+ ss7_block_cics(linkset, e->cgu.startcic, e->cgu.endcic, e->cgu.status, 0);
+ isup_cgua(linkset->ss7, e->cgu.startcic, e->cgu.endcic, p->dpc, e->cgu.status, e->cgu.type);
break;
case ISUP_EVENT_BLO:
chanpos = ss7_find_cic(linkset, e->blo.cic);
break;
}
p = linkset->pvts[chanpos];
- ast_log(LOG_DEBUG, "Blocking CIC %d\n", e->blo.cic);
+ ast_debug(1, "Blocking CIC %d\n", e->blo.cic);
ast_mutex_lock(&p->lock);
p->remotelyblocked = 1;
ast_mutex_unlock(&p->lock);
- isup_bla(linkset->ss7, e->blo.cic);
+ isup_bla(linkset->ss7, e->blo.cic, p->dpc);
break;
case ISUP_EVENT_UBL:
chanpos = ss7_find_cic(linkset, e->ubl.cic);
break;
}
p = linkset->pvts[chanpos];
- ast_log(LOG_DEBUG, "Unblocking CIC %d\n", e->ubl.cic);
+ ast_debug(1, "Unblocking CIC %d\n", e->ubl.cic);
ast_mutex_lock(&p->lock);
p->remotelyblocked = 0;
ast_mutex_unlock(&p->lock);
- isup_uba(linkset->ss7, e->ubl.cic);
+ isup_uba(linkset->ss7, e->ubl.cic, p->dpc);
break;
case ISUP_EVENT_CON:
case ISUP_EVENT_ANM:
}
break;
default:
- ast_log(LOG_DEBUG, "Unknown event %s\n", ss7_event2str(e->e));
+ ast_debug(1, "Unknown event %s\n", ss7_event2str(e->e));
break;
}
}
static void zt_ss7_message(struct ss7 *ss7, char *s)
{
+#if 0
int i;
for (i = 0; i < NUM_SPANS; i++)
break;
ast_verbose("[%d] %s", i+1, s);
+#else
+ ast_verbose("%s", s);
+#endif
}
static void zt_ss7_error(struct ss7 *ss7, char *s)
{
+#if 0
int i;
for (i = 0; i < NUM_SPANS; i++)
if (linksets[i].ss7 == ss7)
break;
- ast_log(LOG_ERROR, "[%d] %s", i+1, s);
+#else
+ ast_log(LOG_ERROR, "%s", s);
+#endif
}
+
#endif /* HAVE_SS7 */
#ifdef HAVE_PRI
zt_close(crv->subs[SUB_REAL].zfd);
pri->pvts[principle]->call = crv->call;
pri_assign_bearer(crv, pri, pri->pvts[principle]);
- if (option_debug)
- ast_log(LOG_DEBUG, "Assigning bearer %d/%d to CRV %d:%d\n",
- pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
- pri->trunkgroup, crv->channel);
+ ast_debug(1, "Assigning bearer %d/%d to CRV %d:%d\n",
+ pri->pvts[principle]->logicalspan, pri->pvts[principle]->prioffset,
+ pri->trunkgroup, crv->channel);
wakeup_sub(crv, SUB_REAL, pri);
}
return principle;
static void apply_plan_to_number(char *buf, size_t size, const struct zt_pri *pri, const char *number, const int plan)
{
+ if (pri->dialplan == -2) { /* autodetect the TON but leave the number untouched */
+ snprintf(buf, size, "%s", number);
+ return;
+ }
switch (plan) {
case PRI_INTERNATIONAL_ISDN: /* Q.931 dialplan == 0x11 international dialplan => prepend international prefix digits */
snprintf(buf, size, "%s%s", pri->internationalprefix, number);
int nextidle = -1;
struct ast_channel *c;
struct timeval tv, lowest, *next;
- struct timeval lastidle = { 0, 0 };
+ struct timeval lastidle = ast_tvnow();
int doidling=0;
char *cc;
char idlen[80];
int cause=0;
struct zt_pvt *crv;
pthread_t threadid;
- pthread_attr_t attr;
char ani2str[6];
char plancallingnum[256];
char plancallingani[256];
char calledtonstr[10];
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
- gettimeofday(&lastidle, NULL);
if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
/* Need to do idle dialing, check to be sure though */
cc = strchr(pri->idleext, '@');
}
} else
ast_log(LOG_WARNING, "Unable to request channel 'Zap/%s' for idle call\n", idlen);
- gettimeofday(&lastidle, NULL);
+ lastidle = ast_tvnow();
}
} else if ((haveidles < pri->minunused) &&
(activeidles > pri->minidle)) {
pri_restart(pri->dchans[which]);
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
+ ast_debug(1, "Got event %s (%d) on D-channel for span %d\n", event2str(x), x, pri->span);
} else if (fds[which].revents & POLLIN) {
e = pri_check_event(pri->dchans[which]);
}
pri_dump_event(pri->dchans[which], e);
if (e->e != PRI_EVENT_DCHAN_DOWN)
pri->dchanavail[which] |= DCHAN_UP;
+
+ if ((e->e != PRI_EVENT_DCHAN_UP) && (e->e != PRI_EVENT_DCHAN_DOWN) && (pri->pri != pri->dchans[which]))
+ /* Must be an NFAS group that has the secondary dchan active */
+ pri->pri = pri->dchans[which];
+
switch (e->e) {
case PRI_EVENT_DCHAN_UP:
if (option_verbose > 1)
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
/* queue DTMF frame if the PBX for this call was already started (we're forwarding KEYPAD_DIGITs further on */
- if (pri->overlapdial && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
+ if ((pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->digit.call && pri->pvts[chanpos]->owner) {
/* how to do that */
int digitlen = strlen(e->digit.digits);
char digit;
if (chanpos > -1) {
ast_mutex_lock(&pri->pvts[chanpos]->lock);
/* queue DTMF frame if the PBX for this call was already started (we're forwarding INFORMATION further on */
- if (pri->overlapdial && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
+ if ((pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING) && pri->pvts[chanpos]->call==e->ring.call && pri->pvts[chanpos]->owner) {
/* how to do that */
int digitlen = strlen(e->ring.callednum);
char digit;
PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
break;
} else {
- ast_log(LOG_WARNING, "Ring requested on channel %d/%d already in use on span %d. Hanging up owner.\n",
+ /* This is where we handle initial glare */
+ ast_debug(1, "Ring requested on channel %d/%d already in use or previously requested on span %d. Attempting to renegotiate channel.\n",
PRI_SPAN(e->ring.channel), PRI_CHANNEL(e->ring.channel), pri->span);
- if (pri->pvts[chanpos]->realcall)
- pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
- else
- pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
chanpos = -1;
}
pri->pvts[chanpos]->exten[1] = '\0';
}
/* Make sure extension exists (or in overlap dial mode, can exist) */
- if ((pri->overlapdial && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
+ if (((pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING) && ast_canmatch_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) ||
ast_exists_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/* Setup law */
int law;
res = set_actual_gain(pri->pvts[chanpos]->subs[SUB_REAL].zfd, 0, pri->pvts[chanpos]->rxgain, pri->pvts[chanpos]->txgain, law);
if (res < 0)
ast_log(LOG_WARNING, "Unable to set gains on channel %d\n", pri->pvts[chanpos]->channel);
- if (e->ring.complete || !pri->overlapdial) {
+ if (e->ring.complete || !(pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING)) {
/* Just announce proceeding */
pri->pvts[chanpos]->proceeding = 1;
pri_proceeding(pri->pri, e->ring.call, PVT_TO_CHANNEL(pri->pvts[chanpos]), 0);
pri->pvts[chanpos]->callingpres = e->ring.callingpres;
/* Start PBX */
- if (pri->overlapdial && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
+ if ((pri->overlapdial & ZAP_OVERLAPDIAL_INCOMING) && ast_matchmore_extension(NULL, pri->pvts[chanpos]->context, pri->pvts[chanpos]->exten, 1, pri->pvts[chanpos]->cid_num)) {
/* Release the PRI lock while we create the channel */
ast_mutex_unlock(&pri->lock);
if (crv) {
pri_assign_bearer(crv, pri, pri->pvts[chanpos]);
c = zt_new(crv, AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
pri->pvts[chanpos]->owner = &inuse;
- if (option_debug)
- ast_log(LOG_DEBUG, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
+ ast_debug(1, "Started up crv %d:%d on bearer channel %d\n", pri->trunkgroup, crv->channel, crv->bearer->channel);
} else {
c = zt_new(pri->pvts[chanpos], AST_STATE_RESERVED, 0, SUB_REAL, law, e->ring.ctype);
}
pbx_builtin_setvar_helper(c, "PRIREDIRECTREASON", redirectingreason2str(e->ring.redirectingreason));
ast_mutex_lock(&pri->lock);
- if (c && !ast_pthread_create(&threadid, &attr, ss_thread, c)) {
+ if (c && !ast_pthread_create_detached(&threadid, NULL, ss_thread, c)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Accepting overlap call from '%s' to '%s' on channel %d/%d, span %d\n",
plancallingnum, S_OR(pri->pvts[chanpos]->exten, "<unspecified>"),
if (crv)
ast_mutex_unlock(&crv->lock);
ast_mutex_unlock(&pri->pvts[chanpos]->lock);
- } else
- pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+ } else {
+ if (e->ring.flexible)
+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION);
+ else
+ pri_hangup(pri->pri, e->ring.call, PRI_CAUSE_REQUESTED_CHAN_UNAVAIL);
+ }
break;
case PRI_EVENT_RINGING:
chanpos = pri_find_principle(pri, e->ringing.channel);
zt_enable_ec(pri->pvts[chanpos]);
pri->pvts[chanpos]->subs[SUB_REAL].needringing = 1;
pri->pvts[chanpos]->alerting = 1;
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Deferring ringing notification because of extra digits to dial...\n");
- }
+ } else
+ ast_debug(1, "Deferring ringing notification because of extra digits to dial...\n");
+
#ifdef PRI_PROGRESS_MASK
if (e->ringing.progressmask & PRI_PROG_INBAND_AVAILABLE) {
#else
}
ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
+ ast_debug(1, "Queuing frame from PRI_EVENT_PROGRESS on channel %d/%d span %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
zap_queue_frame(pri->pvts[chanpos], &f, pri);
#ifdef PRI_PROGRESS_MASK
if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
struct ast_frame f = { AST_FRAME_CONTROL, AST_CONTROL_PROCEEDING, };
ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
+ ast_debug(1, "Queuing frame from PRI_EVENT_PROCEEDING on channel %d/%d span %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset,pri->span);
zap_queue_frame(pri->pvts[chanpos], &f, pri);
#ifdef PRI_PROGRESS_MASK
if (e->proceeding.progressmask & PRI_PROG_INBAND_AVAILABLE) {
pri->pvts[chanpos]->dsp_features = 0;
}
if (pri->pvts[chanpos]->realcall && (pri->pvts[chanpos]->realcall->sig == SIG_FXSKS)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Starting up GR-303 trunk now that we got CONNECT...\n");
+ ast_debug(1, "Starting up GR-303 trunk now that we got CONNECT...\n");
x = ZT_START;
res = ioctl(pri->pvts[chanpos]->subs[SUB_REAL].zfd, ZT_HOOK, &x);
if (res < 0) {
if (res < 0) {
ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", pri->pvts[chanpos]->channel);
pri->pvts[chanpos]->dop.dialstr[0] = '\0';
- } else {
- if (option_debug)
- ast_log(LOG_DEBUG, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
- }
+ } else
+ ast_debug(1, "Sent deferred digit string: %s\n", pri->pvts[chanpos]->dop.dialstr);
+
pri->pvts[chanpos]->dop.dialstr[0] = '\0';
} else if (pri->pvts[chanpos]->confirmanswer) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
+ ast_debug(1, "Waiting on answer confirmation on channel %d!\n", pri->pvts[chanpos]->channel);
} else {
pri->pvts[chanpos]->subs[SUB_REAL].needanswer =1;
/* Enable echo cancellation if it's not on already */
else if (pri->pvts[chanpos]->owner) {
/* Queue a BUSY instead of a hangup if our cause is appropriate */
pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- switch (e->hangup.cause) {
- case PRI_CAUSE_USER_BUSY:
- pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
- break;
- case PRI_CAUSE_CALL_REJECTED:
- case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
- case PRI_CAUSE_SWITCH_CONGESTION:
- case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
- pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
- break;
- default:
+ if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ else {
+ switch (e->hangup.cause) {
+ case PRI_CAUSE_USER_BUSY:
+ pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+ break;
+ case PRI_CAUSE_CALL_REJECTED:
+ case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ case PRI_CAUSE_SWITCH_CONGESTION:
+ case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+ pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+ break;
+ default:
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
}
}
if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup\n",
- pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span);
+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup, cause %d\n",
+ pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, e->hangup.cause);
} else {
pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause);
pri->pvts[chanpos]->call = NULL;
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner) {
pri->pvts[chanpos]->owner->hangupcause = e->hangup.cause;
- switch (e->hangup.cause) {
- case PRI_CAUSE_USER_BUSY:
- pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
- break;
- case PRI_CAUSE_CALL_REJECTED:
- case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
- case PRI_CAUSE_SWITCH_CONGESTION:
- case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
- case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
- pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
- break;
- default:
+ if (pri->pvts[chanpos]->owner->_state == AST_STATE_UP)
pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ else {
+ switch (e->hangup.cause) {
+ case PRI_CAUSE_USER_BUSY:
+ pri->pvts[chanpos]->subs[SUB_REAL].needbusy =1;
+ break;
+ case PRI_CAUSE_CALL_REJECTED:
+ case PRI_CAUSE_NETWORK_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+ case PRI_CAUSE_SWITCH_CONGESTION:
+ case PRI_CAUSE_DESTINATION_OUT_OF_ORDER:
+ case PRI_CAUSE_NORMAL_TEMPORARY_FAILURE:
+ pri->pvts[chanpos]->subs[SUB_REAL].needcongestion =1;
+ break;
+ default:
+ pri->pvts[chanpos]->owner->_softhangup |= AST_SOFTHANGUP_DEV;
+ }
}
if (option_verbose > 2)
- ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span);
+ ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d got hangup request, cause %d\n", PRI_SPAN(e->hangup.channel), PRI_CHANNEL(e->hangup.channel), pri->span, e->hangup.cause);
if (e->hangup.aoc_units > -1)
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Channel %d/%d, span %d received AOC-E charging %d unit%s\n",
if (pri->pvts[x] && pri->pvts[x]->resetting) {
chanpos = x;
ast_mutex_lock(&pri->pvts[chanpos]->lock);
- if (option_debug)
- ast_log(LOG_DEBUG, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
- pri->pvts[chanpos]->prioffset, pri->span);
+ ast_debug(1, "Assuming restart ack is really for channel %d/%d span %d\n", pri->pvts[chanpos]->logicalspan,
+ pri->pvts[chanpos]->prioffset, pri->span);
if (pri->pvts[chanpos]->realcall)
pri_hangup_all(pri->pvts[chanpos]->realcall, pri);
else if (pri->pvts[chanpos]->owner) {
pri->pvts[chanpos]->setup_ack = 1;
/* Send any queued digits */
for (x = 0;x < strlen(pri->pvts[chanpos]->dialdest); x++) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
+ ast_debug(1, "Sending pending digit '%c'\n", pri->pvts[chanpos]->dialdest[x]);
pri_information(pri->pri, pri->pvts[chanpos]->call,
pri->pvts[chanpos]->dialdest[x]);
}
}
break;
default:
- if (option_debug)
- ast_log(LOG_DEBUG, "Event: %d\n", e->e);
+ ast_debug(1, "Event: %d\n", e->e);
}
}
ast_mutex_unlock(&pri->lock);
pri->dchans[i] = pri_new(pri->fds[i], pri->nodetype, pri->switchtype);
/* Force overlap dial if we're doing GR-303! */
if (pri->switchtype == PRI_SWITCH_GR303_TMC)
- pri->overlapdial = 1;
- pri_set_overlapdial(pri->dchans[i],pri->overlapdial);
+ pri->overlapdial |= ZAP_OVERLAPDIAL_BOTH;
+ pri_set_overlapdial(pri->dchans[i],(pri->overlapdial & ZAP_OVERLAPDIAL_OUTGOING)?1:0);
/* Enslave to master if appropriate */
if (i)
pri_enslave(pri->dchans[0], pri->dchans[i]);
info_str = pri_dump_info_str(pris[span-1].pri);
if (info_str) {
ast_cli(fd, "%s", info_str);
- free(info_str);
+ ast_free(info_str);
}
#else
pri_dump_info(pris[span-1].pri);
#endif
- ast_cli(fd, "\n");
+ ast_cli(fd, "Overlap Recv: %s\n\n", (pris[span-1].overlapdial & ZAP_OVERLAPDIAL_INCOMING)?"Yes":"No");
}
}
return RESULT_SUCCESS;
static int zap_destroy_channel(int fd, int argc, char **argv)
{
- int channel = 0;
- struct zt_pvt *tmp = NULL;
- struct zt_pvt *prev = NULL;
+ int channel;
- if (argc != 4) {
+ if (argc != 4)
return RESULT_SHOWUSAGE;
- }
+
channel = atoi(argv[3]);
- tmp = iflist;
- while (tmp) {
- if (tmp->channel == channel) {
- destroy_channel(prev, tmp, 1);
- return RESULT_SUCCESS;
- }
- prev = tmp;
- tmp = tmp->next;
- }
- return RESULT_FAILURE;
+ return zap_destroy_channel_bynum(channel);
}
static int setup_zap(int reload);
if (option_verbose > 0)
ast_verbose(VERBOSE_PREFIX_1 "Destroying channels and reloading zaptel configuration.\n");
while (iflist) {
- if (option_debug)
- ast_log(LOG_DEBUG, "Destroying zaptel channel no. %d\n", iflist->channel);
+ ast_debug(1, "Destroying zaptel channel no. %d\n", iflist->channel);
/* Also updates iflist: */
destroy_channel(NULL, iflist, 1);
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Channels destroyed. Now re-reading config.\n");
+ ast_debug(1, "Channels destroyed. Now re-reading config.\n");
if (setup_zap(1) != 0) {
ast_log(LOG_WARNING, "Reload channels from zap config failed!\n");
return 1;
{
#define FORMAT "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
#define FORMAT2 "%7s %-10.10s %-15.15s %-10.10s %-20.20s %-10.10s %-10.10s\n"
+ unsigned int targetnum = 0;
+ int filtertype = 0;
struct zt_pvt *tmp = NULL;
char tmps[20] = "";
char statestr[20] = "";
lock = &iflock;
start = iflist;
+ /* syntax: zap show channels [ group <group> | context <context> | trunkgroup <trunkgroup> ] */
+
+ if (!((argc == 3) || (argc == 5)))
+ return RESULT_SHOWUSAGE;
+
+ if (argc == 5) {
#ifdef HAVE_PRI
- if (argc == 4) {
- if ((trunkgroup = atoi(argv[3])) < 1)
- return RESULT_SHOWUSAGE;
- for (x = 0; x < NUM_SPANS; x++) {
- if (pris[x].trunkgroup == trunkgroup) {
- pri = pris + x;
- break;
+ if (!strcasecmp(argv[3], "trunkgroup")) {
+ /* this option requires no special handling, so leave filtertype to zero */
+ if ((trunkgroup = atoi(argv[4])) < 1)
+ return RESULT_SHOWUSAGE;
+ for (x = 0; x < NUM_SPANS; x++) {
+ if (pris[x].trunkgroup == trunkgroup) {
+ pri = pris + x;
+ break;
+ }
}
+ if (pri) {
+ start = pri->crvs;
+ lock = &pri->lock;
+ } else {
+ ast_cli(fd, "No such trunk group %d\n", trunkgroup);
+ return RESULT_FAILURE;
+ }
+ } else
+#endif
+ if (!strcasecmp(argv[3], "group")) {
+ targetnum = atoi(argv[4]);
+ if ((targetnum < 0) || (targetnum > 63))
+ return RESULT_SHOWUSAGE;
+ targetnum = 1 << targetnum;
+ filtertype = 1;
+ } else if (!strcasecmp(argv[3], "context")) {
+ filtertype = 2;
}
- if (pri) {
- start = pri->crvs;
- lock = &pri->lock;
- } else {
- ast_cli(fd, "No such trunk group %d\n", trunkgroup);
- return RESULT_FAILURE;
- }
- } else
-#endif
- if (argc != 3)
- return RESULT_SHOWUSAGE;
+ }
ast_mutex_lock(lock);
#ifdef HAVE_PRI
tmp = start;
while (tmp) {
+ if (filtertype) {
+ switch(filtertype) {
+ case 1: /* zap show channels group <group> */
+ if (tmp->group != targetnum) {
+ tmp = tmp->next;
+ continue;
+ }
+ break;
+ case 2: /* zap show channels context <context> */
+ if (strcasecmp(tmp->context, argv[4])) {
+ tmp = tmp->next;
+ continue;
+ }
+ break;
+ default:
+ ;
+ }
+ }
if (tmp->channel > 0) {
snprintf(tmps, sizeof(tmps), "%d", tmp->channel);
} else
ast_cli(fd, "Propagated Conference: %d\n", tmp->propconfno);
ast_cli(fd, "Real in conference: %d\n", tmp->inconference);
ast_cli(fd, "DSP: %s\n", tmp->dsp ? "yes" : "no");
+ ast_cli(fd, "TDD: %s\n", tmp->tdd ? "yes" : "no");
ast_cli(fd, "Relax DTMF: %s\n", tmp->dtmfrelax ? "yes" : "no");
ast_cli(fd, "Dialing/CallwaitCAS: %d/%d\n", tmp->dialing, tmp->callwaitcas);
ast_cli(fd, "Default law: %s\n", tmp->law == ZT_LAW_MULAW ? "ulaw" : tmp->law == ZT_LAW_ALAW ? "alaw" : "unknown");
#undef FORMAT2
}
+static int zap_show_version(int fd, int argc, char *argv[])
+{
+ int pseudo_fd = -1;
+ struct zt_versioninfo vi;
+
+ if ((pseudo_fd = open("/dev/zap/ctl", O_RDONLY)) < 0) {
+ ast_cli(fd, "Failed to open control file to get version.\n");
+ return RESULT_SUCCESS;
+ }
+
+ strcpy(vi.version, "Unknown");
+ strcpy(vi.echo_canceller, "Unknown");
+
+ if (ioctl(pseudo_fd, ZT_GETVERSION, &vi))
+ ast_cli(fd, "Failed to get version from control file.\n");
+ else
+ ast_cli(fd, "Zaptel Version: %s Echo Canceller: %s\n", vi.version, vi.echo_canceller);
+
+ close(pseudo_fd);
+
+ return RESULT_SUCCESS;
+}
+
static const char show_channels_usage[] =
- "Usage: zap show channels\n"
- " Shows a list of available channels\n";
+ "Usage: zap show channels [ trunkgroup <trunkgroup> | group <group> | context <context> ]\n"
+ " Shows a list of available channels with optional filtering\n"
+ " <group> must be a number between 0 and 63\n";
static const char show_channel_usage[] =
"Usage: zap show channel <chan num>\n"
" Note that this will STOP any running CALL on zaptel channels.\n"
"";
+static char zap_show_version_usage[] =
+ "Usage: zap show version\n"
+ " Shows the Zaptel version in use\n";
+
static struct ast_cli_entry zap_cli[] = {
{ { "zap", "show", "cadences", NULL },
handle_zap_show_cadences, "List cadences",
{ { "zap", "show", "status", NULL},
zap_show_status, "Show all Zaptel cards status",
zap_show_status_usage },
+
+ { { "zap", "show", "version", NULL},
+ zap_show_version, "Show the Zaptel version in use",
+ zap_show_version_usage },
};
#define TRANSFER 0
while (p) {
/* Free any callerid */
if (p->cidspill)
- free(p->cidspill);
+ ast_free(p->cidspill);
/* Close the zapata thingy */
if (p->subs[SUB_REAL].zfd > -1)
zt_close(p->subs[SUB_REAL].zfd);
if (cur_defaultdpc < 0) {
ast_log(LOG_ERROR, "Unspecified defaultdpc!\n");
return -1;
- } else {
- ss7_set_default_dpc(link->ss7, cur_defaultdpc);
}
if (cur_networkindicator < 0) {
linksets[linkset-1].pvts[i]->locallyblocked = 1;
ast_mutex_unlock(&linksets[linkset-1].pvts[i]->lock);
ast_mutex_lock(&linksets[linkset-1].lock);
- isup_blo(linksets[linkset-1].ss7, cic);
+ isup_blo(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
ast_mutex_unlock(&linksets[linkset-1].lock);
}
}
linksets[linkset-1].pvts[i]->locallyblocked = 0;
ast_mutex_unlock(&linksets[linkset-1].pvts[i]->lock);
ast_mutex_lock(&linksets[linkset-1].lock);
- isup_ubl(linksets[linkset-1].ss7, cic);
+ isup_ubl(linksets[linkset-1].ss7, cic, linksets[linkset-1].pvts[i]->dpc);
ast_mutex_unlock(&linksets[linkset-1].lock);
}
}
} else if (!strcasecmp(v->name, "cidstart")) {
if (!strcasecmp(v->value, "ring"))
confp->chan.cid_start = CID_START_RING;
+ else if (!strcasecmp(v->value, "polarity_in"))
+ confp->chan.cid_start = CID_START_POLARITY_IN;
else if (!strcasecmp(v->value, "polarity"))
confp->chan.cid_start = CID_START_POLARITY;
else if (ast_true(v->value))
confp->chan.immediate = ast_true(v->value);
} else if (!strcasecmp(v->name, "transfertobusy")) {
confp->chan.transfertobusy = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "cid_rxgain")) {
+ if (sscanf(v->value, "%f", &confp->chan.cid_rxgain) != 1) {
+ ast_log(LOG_WARNING, "Invalid cid_rxgain: %s\n", v->value);
+ }
} else if (!strcasecmp(v->name, "rxgain")) {
if (sscanf(v->value, "%f", &confp->chan.rxgain) != 1) {
ast_log(LOG_WARNING, "Invalid rxgain: %s\n", v->value);
ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
else
confp->chan.amaflags = y;
+ } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
+ confp->chan.polarityonanswerdelay = atoi(v->value);
+ } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
+ confp->chan.answeronpolarityswitch = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
+ confp->chan.hanguponpolarityswitch = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "sendcalleridafter")) {
+ confp->chan.sendcalleridafter = atoi(v->value);
} else if (!reload){
if (!strcasecmp(v->name, "signalling")) {
confp->chan.outsigmod = -1;
confp->pri.dialplan = PRI_LOCAL_ISDN + 1;
} else if (!strcasecmp(v->value, "dynamic")) {
confp->pri.dialplan = -1;
+ } else if (!strcasecmp(v->value, "redundant")) {
+ confp->pri.dialplan = -2;
} else {
ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
}
confp->pri.localdialplan = PRI_LOCAL_ISDN + 1;
} else if (!strcasecmp(v->value, "dynamic")) {
confp->pri.localdialplan = -1;
+ } else if (!strcasecmp(v->value, "redundant")) {
+ confp->pri.localdialplan = -2;
} else {
- ast_log(LOG_WARNING, "Unknown PRI dialplan '%s' at line %d.\n", v->value, v->lineno);
+ ast_log(LOG_WARNING, "Unknown PRI localdialplan '%s' at line %d.\n", v->value, v->lineno);
}
} else if (!strcasecmp(v->name, "switchtype")) {
if (!strcasecmp(v->value, "national"))
} else if (!strcasecmp(v->name, "idledial")) {
ast_copy_string(confp->pri.idledial, v->value, sizeof(confp->pri.idledial));
} else if (!strcasecmp(v->name, "overlapdial")) {
- confp->pri.overlapdial = ast_true(v->value);
+ if (ast_true(v->value)) {
+ confp->pri.overlapdial = ZAP_OVERLAPDIAL_BOTH;
+ } else if (!strcasecmp(v->value, "incoming")) {
+ confp->pri.overlapdial = ZAP_OVERLAPDIAL_INCOMING;
+ } else if (!strcasecmp(v->value, "outgoing")) {
+ confp->pri.overlapdial = ZAP_OVERLAPDIAL_OUTGOING;
+ } else if (!strcasecmp(v->value, "both") || ast_true(v->value)) {
+ confp->pri.overlapdial = ZAP_OVERLAPDIAL_BOTH;
+ } else {
+ confp->pri.overlapdial = ZAP_OVERLAPDIAL_NONE;
+ }
} else if (!strcasecmp(v->name, "pritimer")) {
#ifdef PRI_GETSET_TIMERS
char *timerc, *c;
cur_networkindicator = SS7_NI_INT_SPARE;
else
cur_networkindicator = -1;
+ } else if (!strcasecmp(v->name, "ss7_internationalprefix")) {
+ ast_copy_string(confp->ss7.internationalprefix, v->value, sizeof(confp->ss7.internationalprefix));
+ } else if (!strcasecmp(v->name, "ss7_nationalprefix")) {
+ ast_copy_string(confp->ss7.nationalprefix, v->value, sizeof(confp->ss7.nationalprefix));
+ } else if (!strcasecmp(v->name, "ss7_subscriberprefix")) {
+ ast_copy_string(confp->ss7.subscriberprefix, v->value, sizeof(confp->ss7.subscriberprefix));
+ } else if (!strcasecmp(v->name, "ss7_unknownprefix")) {
+ ast_copy_string(confp->ss7.unknownprefix, v->value, sizeof(confp->ss7.unknownprefix));
+ } else if (!strcasecmp(v->name, "ss7_called_nai")) {
+ if (!strcasecmp(v->value, "national")) {
+ confp->ss7.called_nai = SS7_NAI_NATIONAL;
+ } else if (!strcasecmp(v->value, "international")) {
+ confp->ss7.called_nai = SS7_NAI_INTERNATIONAL;
+ } else if (!strcasecmp(v->value, "subscriber")) {
+ confp->ss7.called_nai = SS7_NAI_SUBSCRIBER;
+ } else if (!strcasecmp(v->value, "dynamic")) {
+ confp->ss7.called_nai = SS7_NAI_DYNAMIC;
+ } else {
+ ast_log(LOG_WARNING, "Unknown SS7 called_nai '%s' at line %d.\n", v->value, v->lineno);
+ }
+ } else if (!strcasecmp(v->name, "ss7_calling_nai")) {
+ if (!strcasecmp(v->value, "national")) {
+ confp->ss7.calling_nai = SS7_NAI_NATIONAL;
+ } else if (!strcasecmp(v->value, "international")) {
+ confp->ss7.calling_nai = SS7_NAI_INTERNATIONAL;
+ } else if (!strcasecmp(v->value, "subscriber")) {
+ confp->ss7.calling_nai = SS7_NAI_SUBSCRIBER;
+ } else if (!strcasecmp(v->value, "dynamic")) {
+ confp->ss7.calling_nai = SS7_NAI_DYNAMIC;
+ } else {
+ ast_log(LOG_WARNING, "Unknown SS7 calling_nai '%s' at line %d.\n", v->value, v->lineno);
+ }
} else if (!strcasecmp(v->name, "sigchan")) {
int sigchan, res;
sigchan = atoi(v->value);
}
}
close(ctlfd);
- } else if (!strcasecmp(v->name, "polarityonanswerdelay")) {
- confp->chan.polarityonanswerdelay = atoi(v->value);
- } else if (!strcasecmp(v->name, "answeronpolarityswitch")) {
- confp->chan.answeronpolarityswitch = ast_true(v->value);
- } else if (!strcasecmp(v->name, "hanguponpolarityswitch")) {
- confp->chan.hanguponpolarityswitch = ast_true(v->value);
- } else if (!strcasecmp(v->name, "sendcalleridafter")) {
- confp->chan.sendcalleridafter = atoi(v->value);
} else if (!strcasecmp(v->name, "defaultcic")) {
ast_copy_string(defaultcic, v->value, sizeof(defaultcic));
} else if (!strcasecmp(v->name, "defaultozz")) {
len = tdd_generate(p->tdd, buf, text);
if (len < 1) {
ast_log(LOG_ERROR, "TDD generate (len %d) failed!!\n", (int)strlen(text));
- free(mybuf);
+ ast_free(mybuf);
return -1;
}
}
fd = p->subs[index].zfd;
while (len) {
if (ast_check_hangup(c)) {
- free(mybuf);
+ ast_free(mybuf);
return -1;
}
size = len;
fds[0].revents = 0;
res = poll(fds, 1, -1);
if (!res) {
- if (option_debug)
- ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
+ ast_debug(1, "poll (for write) ret. 0 on channel %d\n", p->channel);
continue;
}
/* if got exception */
if (fds[0].revents & POLLPRI)
return -1;
if (!(fds[0].revents & POLLOUT)) {
- if (option_debug)
- ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
+ ast_debug(1, "write fd not ready on channel %d\n", p->channel);
continue;
}
res = write(fd, buf, size);
if (res != size) {
if (res == -1) {
- free(mybuf);
+ ast_free(mybuf);
return -1;
}
- if (option_debug)
- ast_log(LOG_DEBUG, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
+ ast_debug(1, "Write returned %d (%s) on channel %d\n", res, strerror(errno), p->channel);
break;
}
len -= size;
buf += size;
}
- free(mybuf);
+ ast_free(mybuf);
return(0);
}