aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authordbailey <dbailey@f38db490-d61c-443f-a65b-d21fe96a405b>2008-08-26 21:59:31 +0000
committerdbailey <dbailey@f38db490-d61c-443f-a65b-d21fe96a405b>2008-08-26 21:59:31 +0000
commita1f4c1f47aabed4894171be230d901f12c2c9e8a (patch)
tree425ae5d42f2678e63fce086173119e69a5a83a11 /channels
parent223527772108b0ba498a649dc3261e65db08822e (diff)
Move the mwi send thread functionality back into the do_monitor thread so that it is easier to manage CID spill resources when do_monitor needs to be killed.
(closes issue #13213) Reported by: bbryant git-svn-id: http://svn.digium.com/svn/asterisk/trunk@140246 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c289
1 files changed, 134 insertions, 155 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 0b21723b0..5a9e1a510 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -276,12 +276,9 @@ AST_MUTEX_DEFINE_STATIC(monlock);
/*! \brief This is the thread for the monitor which checks for input on the channels
which are not currently in use. */
static pthread_t monitor_thread = AST_PTHREADT_NULL;
-static ast_cond_t mwi_thread_complete;
static ast_cond_t ss_thread_complete;
-AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
AST_MUTEX_DEFINE_STATIC(restart_lock);
-static int mwi_thread_count = 0;
static int ss_thread_count = 0;
static int num_restart_pending = 0;
@@ -503,6 +500,24 @@ struct dahdi_subchannel {
#define MAX_SLAVES 4
+/* States for sending MWI message
+ * First three states are required for send Ring Pulse Alert Signal
+ */
+typedef enum {
+ MWI_SEND_NULL = 0,
+ MWI_SEND_SA,
+ MWI_SEND_SA_WAIT,
+ MWI_SEND_PAUSE,
+ MWI_SEND_SPILL,
+ MWI_SEND_CLEANUP,
+ MWI_SEND_DONE,
+} mwisend_states ;
+
+struct mwisend_info {
+ struct timeval pause;
+ mwisend_states mwisend_current;
+};
+
static struct dahdi_pvt {
ast_mutex_t lock;
struct ast_channel *owner; /*!< Our current active owner (if applicable) */
@@ -595,6 +610,7 @@ static struct dahdi_pvt {
unsigned int setup_ack:1;
#endif
unsigned int use_smdi:1; /* Whether to use SMDI on this channel */
+ struct mwisend_info mwisend_data;
struct ast_smdi_interface *smdi_iface; /* The serial port to listen for SMDI data on */
struct dahdi_distRings drings;
@@ -7480,135 +7496,80 @@ quit_no_clean:
return NULL;
}
-/* States for sending MWI message
- * First three states are required for send Ring Pulse Alert Signal
- */
-enum mwisend_states {
- MWI_SEND_SA,
- MWI_SEND_SA_WAIT,
- MWI_SEND_PAUSE,
- MWI_SEND_SPILL,
- MWI_SEND_CLEANUP,
- MWI_SEND_DONE
-};
-
-static void *mwi_send_thread(void *data)
+/*
+* The following three functions (mwi_send_init, mwi_send_process_buffer,
+* mwi_send_process_event) work with the do_monitor thread to generate mwi spills
+* that are sent out via FXA port on voicemail state change. The execution of
+* the mwi send is state driven and can either generate a ring pulse prior to
+* sending the fsk spill or simply send an fsk spill.
+*/
+static int mwi_send_init(struct dahdi_pvt * pvt)
{
- struct mwi_thread_data *mtd = data;
- struct timeval timeout_basis, suspend, now;
- int x, i, res;
- int num_read;
- enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
-
- ast_mutex_lock(&mwi_thread_lock);
- mwi_thread_count++;
- ast_mutex_unlock(&mwi_thread_lock);
+ int x, res;
+ pvt->mwisendactive = 1;
+ pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL; /*Assume FSK only */
/* Determine how this spill is to be sent */
if(mwisend_rpas) {
- mwi_send_state = MWI_SEND_SA;
+ pvt->mwisend_data.mwisend_current = MWI_SEND_SA;
}
- gettimeofday(&timeout_basis, NULL);
-
- mtd->pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
- if (!mtd->pvt->cidspill) {
- mtd->pvt->mwisendactive = 0;
- ast_free(mtd);
- return NULL;
+ pvt->cidspill = ast_calloc(1, MAX_CALLERID_SIZE);
+ if (!pvt->cidspill) {
+ pvt->mwisendactive = 0;
+ return -1;
}
x = DAHDI_FLUSH_BOTH;
- res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
+ res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_FLUSH, &x);
x = 3000;
- ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
- mtd->pvt->cidlen = vmwi_generate(mtd->pvt->cidspill, has_voicemail(mtd->pvt), CID_MWI_TYPE_MDMF_FULL,
- AST_LAW(mtd->pvt), mtd->pvt->cid_name, mtd->pvt->cid_num, 0);
- mtd->pvt->cidpos = 0;
-
- while (MWI_SEND_DONE != mwi_send_state) {
- num_read = 0;
- gettimeofday(&now, NULL);
- if ( 10 < (now.tv_sec - timeout_basis.tv_sec)) {
- ast_log(LOG_WARNING, "MWI Send TIMEOUT in state %d\n", mwi_send_state);
- goto quit;
- }
+ ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_ONHOOKTRANSFER, &x);
+ pvt->cidlen = vmwi_generate(pvt->cidspill, has_voicemail(pvt), CID_MWI_TYPE_MDMF_FULL,
+ AST_LAW(pvt), pvt->cid_name, pvt->cid_num, 0);
+ pvt->cidpos = 0;
+ return 0;
+}
- i = DAHDI_IOMUX_READ | DAHDI_IOMUX_SIGEVENT;
- if ((res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_IOMUX, &i))) {
- ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
- goto quit;
- }
+static int mwi_send_process_buffer(struct dahdi_pvt * pvt, int num_read)
+{
+ struct timeval now;
+ int res;
- if (i & DAHDI_IOMUX_SIGEVENT) {
- /* If we get an event, screen out events that we do not act on.
- * Otherwise, let handle_init_event determine what is needed
- */
- res = dahdi_get_event(mtd->pvt->subs[SUB_REAL].dfd);
- switch (res) {
- case DAHDI_EVENT_RINGEROFF:
- if(mwi_send_state == MWI_SEND_SA_WAIT) {
- if (dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
- ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s\n", strerror(errno));
- goto quit;
- }
- mwi_send_state = MWI_SEND_PAUSE;
- gettimeofday(&suspend, NULL);
- }
- break;
- case DAHDI_EVENT_RINGERON:
- case DAHDI_EVENT_HOOKCOMPLETE:
- break;
- default:
- /* Got to the default init event handler */
- if (0 < handle_init_event(mtd->pvt, res)) {
- /* I've spawned a thread, get out */
- goto quit;
- }
- break;
- }
- } else if (i & DAHDI_IOMUX_READ) {
- if ((num_read = read(mtd->pvt->subs[SUB_REAL].dfd, mtd->buf, sizeof(mtd->buf))) < 0) {
- if (errno != ELAST) {
- ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
- goto quit;
- }
- break;
- }
- }
- /* Perform mwi send action */
- switch ( mwi_send_state) {
+ /* sanity check to catch if this had been interrupted previously
+ * i.e. state says there is more to do but there is no spill allocated
+ */
+ if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current && !pvt->cidspill) {
+ pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
+ } else if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
+ /* Normal processing -- Perform mwi send action */
+ switch ( pvt->mwisend_data.mwisend_current) {
case MWI_SEND_SA:
/* Send the Ring Pulse Signal Alert */
- res = ioctl(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
+ res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SETCADENCE, &AS_RP_cadence);
if (res) {
ast_log(LOG_WARNING, "Unable to set RP-AS ring cadence: %s\n", strerror(errno));
goto quit;
}
- dahdi_set_hook(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_RING);
- mwi_send_state = MWI_SEND_SA_WAIT;
+ res = dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RING);
+ pvt->mwisend_data.mwisend_current = MWI_SEND_SA_WAIT;
+ break;
+ case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
+ break;
+ case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
+ gettimeofday(&now, NULL);
+ if ((int)(now.tv_sec - pvt->mwisend_data.pause.tv_sec) * 1000000 + (int)now.tv_usec - (int)pvt->mwisend_data.pause.tv_usec > 500000) {
+ pvt->mwisend_data.mwisend_current = MWI_SEND_SPILL;
+ }
break;
- case MWI_SEND_SA_WAIT: /* do nothing until I get RINGEROFF event */
- break;
- case MWI_SEND_PAUSE: /* Wait between alert and spill - min of 500 mS*/
- gettimeofday(&now, NULL);
- if ((int)(now.tv_sec - suspend.tv_sec) * 1000000 + (int)now.tv_usec - (int)suspend.tv_usec > 500000) {
- mwi_send_state = MWI_SEND_SPILL;
- }
- break;
case MWI_SEND_SPILL:
/* We read some number of bytes. Write an equal amount of data */
if(0 < num_read) {
- if (num_read > mtd->pvt->cidlen - mtd->pvt->cidpos)
- num_read = mtd->pvt->cidlen - mtd->pvt->cidpos;
- res = write(mtd->pvt->subs[SUB_REAL].dfd, mtd->pvt->cidspill + mtd->pvt->cidpos, num_read);
+ if (num_read > pvt->cidlen - pvt->cidpos)
+ num_read = pvt->cidlen - pvt->cidpos;
+ res = write(pvt->subs[SUB_REAL].dfd, pvt->cidspill + pvt->cidpos, num_read);
if (res > 0) {
- mtd->pvt->cidpos += res;
- if (mtd->pvt->cidpos >= mtd->pvt->cidlen) {
- ast_free(mtd->pvt->cidspill);
- mtd->pvt->cidspill = NULL;
- mtd->pvt->cidpos = 0;
- mtd->pvt->cidlen = 0;
- mwi_send_state = MWI_SEND_CLEANUP;
+ pvt->cidpos += res;
+ if (pvt->cidpos >= pvt->cidlen) {
+ pvt->mwisend_data.mwisend_current = MWI_SEND_CLEANUP;
}
} else {
ast_log(LOG_WARNING, "MWI Send Write failed: %s\n", strerror(errno));
@@ -7618,7 +7579,7 @@ static void *mwi_send_thread(void *data)
break;
case MWI_SEND_CLEANUP:
/* For now, do nothing */
- mwi_send_state = MWI_SEND_DONE;
+ pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
break;
default:
/* Should not get here, punt*/
@@ -7627,22 +7588,54 @@ static void *mwi_send_thread(void *data)
}
}
-quit:
- if(mtd->pvt->cidspill) {
- ast_free(mtd->pvt->cidspill);
- mtd->pvt->cidspill = NULL;
+ if (MWI_SEND_DONE == pvt->mwisend_data.mwisend_current) {
+ if(pvt->cidspill) {
+ ast_free(pvt->cidspill);
+ pvt->cidspill = NULL;
+ pvt->cidpos = 0;
+ pvt->cidlen = 0;
+ }
+ pvt->mwisendactive = 0;
}
- mtd->pvt->mwisendactive = 0;
- ast_free(mtd);
+ return 0;
+quit:
+ return -1;
+}
- ast_mutex_lock(&mwi_thread_lock);
- mwi_thread_count--;
- ast_cond_signal(&mwi_thread_complete);
- ast_mutex_unlock(&mwi_thread_lock);
+static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
+{
+ int handled = 0;
- return NULL;
-}
+ if (MWI_SEND_DONE != pvt->mwisend_data.mwisend_current) {
+ switch (event) {
+ case DAHDI_EVENT_RINGEROFF:
+ if(pvt->mwisend_data.mwisend_current == MWI_SEND_SA_WAIT) {
+ handled = 1;
+
+ if (dahdi_set_hook(pvt->subs[SUB_REAL].dfd, DAHDI_RINGOFF) ) {
+ ast_log(LOG_WARNING, "Unable to finsh RP-AS: %s mwi send aborted\n", strerror(errno));
+ if(pvt->cidspill) {
+ ast_free(pvt->cidspill);
+ pvt->cidspill = NULL;
+ }
+ pvt->mwisend_data.mwisend_current = MWI_SEND_DONE;
+ pvt->mwisendactive = 0;
+ } else {
+ pvt->mwisend_data.mwisend_current = MWI_SEND_PAUSE;
+ gettimeofday(&pvt->mwisend_data.pause, NULL);
+ }
+ }
+ break;
+ case DAHDI_EVENT_RINGERON:
+ case DAHDI_EVENT_HOOKCOMPLETE:
+ break;
+ default:
+ break;
+ }
+ }
+ return handled;
+}
/* destroy a DAHDI channel, identified by its number */
static int dahdi_destroy_channel_bynum(int channel)
@@ -7941,14 +7934,14 @@ static void *do_monitor(void *data)
i = iflist;
while (i) {
if ((i->subs[SUB_REAL].dfd > -1) && i->sig && (!i->radio)) {
- if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive && !i->mwisendactive) {
+ if (!i->owner && !i->subs[SUB_REAL].owner && !i->mwimonitoractive ) {
/* This needs to be watched, as it lacks an owner */
pfds[count].fd = i->subs[SUB_REAL].dfd;
pfds[count].events = POLLPRI;
pfds[count].revents = 0;
/* If we are monitoring for VMWI or sending CID, we need to
read from the channel as well */
- if (i->cidspill || i->mwimonitor_fsk)
+ if (i->cidspill || i->mwisendactive || i->mwimonitor_fsk)
pfds[count].events |= POLLIN;
count++;
}
@@ -7987,29 +7980,18 @@ static void *do_monitor(void *data)
if (!last->mwisendactive && last->sig & __DAHDI_SIG_FXO) {
res = has_voicemail(last);
if (last->msgstate != res) {
-
- /* This channel has a new voicemail state,
- * initiate a thread to send an MWI message
- */
- pthread_attr_t attr;
- pthread_t threadid;
- struct mwi_thread_data *mtd;
+ /* Set driver resources for signalling VMWI */
res2 = ioctl(last->subs[SUB_REAL].dfd, DAHDI_VMWI, res);
if (res2) {
ast_log(LOG_DEBUG, "Unable to control message waiting led on channel %d: %s\n", last->channel, strerror(errno));
}
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- if ((mtd = ast_calloc(1, sizeof(*mtd)))) {
- last->msgstate = res;
- mtd->pvt = last;
- last->mwisendactive = 1;
- if (ast_pthread_create_background(&threadid, &attr, mwi_send_thread, mtd)) {
- ast_log(LOG_WARNING, "Unable to start mwi send thread on channel %d\n", last->channel);
- ast_free(mtd);
- last->mwisendactive = 0;
- }
+ /* This channel has a new voicemail state,
+ * initiate a mechanism to send an MWI message
+ */
+ if (mwi_send_init(last)) {
+ ast_log(LOG_WARNING, "Unable to initiate mwi send sequence on channel %d\n", last->channel);
}
+ last->msgstate = res;
found ++;
}
}
@@ -8042,8 +8024,8 @@ static void *do_monitor(void *data)
i = i->next;
continue;
}
- if (!i->cidspill && !i->mwimonitor_fsk) {
- ast_log(LOG_WARNING, "Whoa.... I'm reading but have no cidspill (%d)...\n", i->subs[SUB_REAL].dfd);
+ if (!i->mwimonitor_fsk && !i->mwisendactive) {
+ ast_log(LOG_WARNING, "Whoa.... I'm not looking for MWI or sending MWI but am reading (%d)...\n", i->subs[SUB_REAL].dfd);
i = i->next;
continue;
}
@@ -8071,6 +8053,9 @@ static void *do_monitor(void *data)
}
}
}
+ if (i->mwisendactive) {
+ mwi_send_process_buffer(i, res);
+ }
} else {
ast_log(LOG_WARNING, "Read failed with %d: %s\n", res, strerror(errno));
}
@@ -8088,8 +8073,10 @@ static void *do_monitor(void *data)
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);
- ast_mutex_lock(&iflock);
+ if (0 == i->mwisendactive || 0 != mwi_send_process_event(i, res)) {
+ handle_init_event(i, res);
+ }
+ ast_mutex_lock(&iflock);
}
}
i=i->next;
@@ -12053,12 +12040,6 @@ static int dahdi_restart(void)
}
monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
- ast_mutex_lock(&mwi_thread_lock);
- while (mwi_thread_count > 0) {
- ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
- ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
- }
- ast_mutex_unlock(&mwi_thread_lock);
ast_mutex_lock(&ss_thread_lock);
while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
int x = DAHDI_FLASH;
@@ -13564,7 +13545,6 @@ static int __unload_module(void)
}
#endif
- ast_cond_destroy(&mwi_thread_complete);
ast_cond_destroy(&ss_thread_complete);
return 0;
}
@@ -14822,7 +14802,6 @@ static int load_module(void)
ast_manager_register("DAHDIShowChannels", 0, action_dahdishowchannels, "Show status DAHDI channels");
ast_manager_register("DAHDIRestart", 0, action_dahdirestart, "Fully Restart DAHDI channels (terminates calls)");
- ast_cond_init(&mwi_thread_complete, NULL);
ast_cond_init(&ss_thread_complete, NULL);
return res;