diff options
author | dbailey <dbailey@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-08-26 21:59:31 +0000 |
---|---|---|
committer | dbailey <dbailey@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-08-26 21:59:31 +0000 |
commit | a1f4c1f47aabed4894171be230d901f12c2c9e8a (patch) | |
tree | 425ae5d42f2678e63fce086173119e69a5a83a11 /channels | |
parent | 223527772108b0ba498a649dc3261e65db08822e (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.c | 289 |
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; |