diff options
author | file <file@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-09-05 23:48:48 +0000 |
---|---|---|
committer | file <file@f38db490-d61c-443f-a65b-d21fe96a405b> | 2006-09-05 23:48:48 +0000 |
commit | 2993593622bec2056db9560074d9aff5609fa59d (patch) | |
tree | 5591386be584106884a4ed675d417a70c15fe946 | |
parent | 41ca1c9fb93018c5c83aba6816f499f841b41054 (diff) |
Merged revisions 41768,41827,41830,41880,41882,41989,42014,42054 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.2
........
r41768 | file | 2006-09-01 18:49:07 -0400 (Fri, 01 Sep 2006) | 2 lines
Only wipe the redirected audio & video IP/port if it's specified, and trigger a reinvite.
........
r41827 | bweschke | 2006-09-03 10:16:08 -0400 (Sun, 03 Sep 2006) | 3 lines
Setting a retry of 0 is generally not a good idea and shouldn't be allowed. (#7574 - reported by regin)
........
r41830 | bweschke | 2006-09-03 10:50:59 -0400 (Sun, 03 Sep 2006) | 3 lines
Let's NOT spy on Zap/psuedo channels, mmmmmmmmk?
........
r41880 | bweschke | 2006-09-03 13:13:38 -0400 (Sun, 03 Sep 2006) | 3 lines
Don't keep trying the same member in certain strategies when members of the queue are unavailable (#7278 - diLLec reported and patched) - This should have been patched here first and then merged into /trunk. My bad!
........
r41882 | bweschke | 2006-09-03 13:38:22 -0400 (Sun, 03 Sep 2006) | 3 lines
Make sure the forwarded channel inherits variables appropriately when we receive a call forward in the queue. (#7867 - raarts reported and patched)
........
r41989 | oej | 2006-09-04 11:46:07 -0400 (Mon, 04 Sep 2006) | 2 lines
Don't kill the pvt before we have sent ACK on CANCEL (needs more testing before making a release)
........
r42014 | qwell | 2006-09-05 12:27:46 -0400 (Tue, 05 Sep 2006) | 4 lines
Small typo in zapata.conf.sample
Reported by ppyy in 7881
........
r42054 | file | 2006-09-05 16:02:48 -0400 (Tue, 05 Sep 2006) | 2 lines
Merge in last round of spy fixes. This should hopefully eliminate all the issues people have been seeing by distinctly separating what each component (core/spy) is responsible for. Core is responsible for adding a spy to a channel, feeding frames to the spy, removing the spy from a channel, and telling the spy to stop. Spy is responsible for reading frames in, and cleaning up after itself.
........
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2-netsec@42081 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_chanspy.c | 27 | ||||
-rw-r--r-- | apps/app_mixmonitor.c | 24 | ||||
-rw-r--r-- | apps/app_queue.c | 8 | ||||
-rw-r--r-- | channel.c | 111 | ||||
-rw-r--r-- | channels/chan_sip.c | 55 | ||||
-rw-r--r-- | configs/zapata.conf.sample | 2 | ||||
-rw-r--r-- | include/asterisk/chanspy.h | 9 |
7 files changed, 137 insertions, 99 deletions
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 90a8574dd..fe71bbef1 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -131,7 +131,7 @@ static struct ast_channel *local_get_channel_begin_name(char *name) ast_mutex_lock(&modlock); chan = local_channel_walk(NULL); while (chan) { - if (!strncmp(chan->name, name, strlen(name))) { + if (!strncmp(chan->name, name, strlen(name)) && strncmp(chan->name, "Zap/pseudo", 10)) { ret = chan; break; } @@ -207,21 +207,6 @@ static int start_spying(struct ast_channel *chan, struct ast_channel *spychan, s return res; } -static void stop_spying(struct ast_channel *chan, struct ast_channel_spy *spy) -{ - /* If our status has changed to DONE, then the channel we're spying on is gone.... - DON'T TOUCH IT!!! RUN AWAY!!! */ - if (spy->status == CHANSPY_DONE) - return; - - if (!chan) - return; - - ast_mutex_lock(&chan->lock); - ast_channel_spy_remove(chan, spy); - ast_mutex_unlock(&chan->lock); -}; - /* Map 'volume' levels from -4 through +4 into decibel (dB) settings for channel drivers */ @@ -338,7 +323,13 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int } } ast_deactivate_generator(chan); - stop_spying(spyee, &csth.spy); + + if (csth.spy.chan) { + csth.spy.status = CHANSPY_DONE; + ast_mutex_lock(&csth.spy.chan->lock); + ast_channel_spy_remove(csth.spy.chan, &csth.spy); + ast_mutex_unlock(&csth.spy.chan->lock); + } if (option_verbose >= 2) { ast_verbose(VERBOSE_PREFIX_2 "Done Spying on channel %s\n", name); @@ -347,7 +338,7 @@ static int channel_spy(struct ast_channel *chan, struct ast_channel *spyee, int running = 0; } - ast_mutex_destroy(&csth.spy.lock); + ast_channel_spy_free(&csth.spy); return running; } diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index fa4716df0..caff40181 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -109,23 +109,6 @@ AST_APP_OPTIONS(mixmonitor_opts, { AST_APP_OPTION_ARG('W', MUXFLAG_VOLUME, OPT_ARG_VOLUME), }); -static void stopmon(struct ast_channel_spy *spy) -{ - struct ast_channel *chan = spy->chan; - - /* If our status has changed to DONE, then the channel we're spying on is gone.... - DON'T TOUCH IT!!! RUN AWAY!!! */ - if (spy->status == CHANSPY_DONE) - return; - - if (!chan) - return; - - ast_mutex_lock(&chan->lock); - ast_channel_spy_remove(chan, spy); - ast_mutex_unlock(&chan->lock); -} - static int startmon(struct ast_channel *chan, struct ast_channel_spy *spy) { struct ast_channel *peer; @@ -164,9 +147,8 @@ static void *mixmonitor_thread(void *obj) ast_channel_spy_trigger_wait(&mixmonitor->spy); - if (!mixmonitor->spy.chan || mixmonitor->spy.status != CHANSPY_RUNNING) { + if (!mixmonitor->spy.chan || mixmonitor->spy.status != CHANSPY_RUNNING) break; - } while (1) { if (!(f = ast_channel_spy_read_frame(&mixmonitor->spy, SAMPLES_PER_FRAME))) @@ -189,7 +171,7 @@ static void *mixmonitor_thread(void *obj) ast_mutex_unlock(&mixmonitor->spy.lock); - stopmon(&mixmonitor->spy); + ast_channel_spy_free(&mixmonitor->spy); if (option_verbose > 1) ast_verbose(VERBOSE_PREFIX_2 "End MixMonitor Recording %s\n", mixmonitor->name); @@ -199,8 +181,6 @@ static void *mixmonitor_thread(void *obj) ast_verbose(VERBOSE_PREFIX_2 "Executing [%s]\n", mixmonitor->post_process); ast_safe_system(mixmonitor->post_process); } - - ast_mutex_destroy(&mixmonitor->spy.lock); ast_closestream(mixmonitor->fs); diff --git a/apps/app_queue.c b/apps/app_queue.c index 84fb751b1..d3071a819 100644 --- a/apps/app_queue.c +++ b/apps/app_queue.c @@ -777,7 +777,7 @@ static void queue_set_param(struct call_queue *q, const char *param, const char q->periodicannouncefrequency = atoi(val); } else if (!strcasecmp(param, "retry")) { q->retry = atoi(val); - if (q->retry < 0) + if (q->retry <= 0) q->retry = DEFAULT_RETRY; } else if (!strcasecmp(param, "wrapuptime")) { q->wrapuptime = atoi(val); @@ -1518,6 +1518,11 @@ static int ring_entry(struct queue_ent *qe, struct localuser *tmp, int *busies) ast_cdr_busy(qe->chan->cdr); tmp->stillgoing = 0; update_dial_status(qe->parent, tmp->member, status); + + ast_mutex_lock(&qe->parent->lock); + qe->parent->rrpos++; + ast_mutex_unlock(&qe->parent->lock); + (*busies)++; return 0; } else if (status != tmp->oldstatus) @@ -1824,6 +1829,7 @@ static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser o->stillgoing = 0; numnochan++; } else { + ast_channel_inherit_variables(in, o->chan); if (o->chan->cid.cid_num) free(o->chan->cid.cid_num); o->chan->cid.cid_num = NULL; @@ -1017,22 +1017,59 @@ int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy) return 0; } +/* Clean up a channel's spy information */ +static void spy_cleanup(struct ast_channel *chan) +{ + if (AST_LIST_EMPTY(&chan->spies->list)) + return; + if (chan->spies->read_translator.path) + ast_translator_free_path(chan->spies->read_translator.path); + if (chan->spies->write_translator.path) + ast_translator_free_path(chan->spies->write_translator.path); + free(chan->spies); + chan->spies = NULL; + return; +} + +/* Detach a spy from it's channel */ +static void spy_detach(struct ast_channel_spy *spy, struct ast_channel *chan) +{ + ast_mutex_lock(&spy->lock); + + /* We only need to poke them if they aren't already done */ + if (spy->status != CHANSPY_DONE) { + spy->status = CHANSPY_STOP; + spy->chan = NULL; + if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) + ast_cond_signal(&spy->trigger); + } + + /* Print it out while we still have a lock so the structure can't go away (if signalled above) */ + ast_log(LOG_DEBUG, "Spy %s removed from channel %s\n", spy->type, chan->name); + + ast_mutex_unlock(&spy->lock); + + return; +} + void ast_channel_spy_stop_by_type(struct ast_channel *chan, const char *type) { - struct ast_channel_spy *spy; + struct ast_channel_spy *spy = NULL; if (!chan->spies) return; - AST_LIST_TRAVERSE(&chan->spies->list, spy, list) { + AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) { ast_mutex_lock(&spy->lock); if ((spy->type == type) && (spy->status == CHANSPY_RUNNING)) { - spy->status = CHANSPY_STOP; - if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) - ast_cond_signal(&spy->trigger); - } - ast_mutex_unlock(&spy->lock); + ast_mutex_unlock(&spy->lock); + AST_LIST_REMOVE_CURRENT(&chan->spies->list, list); + spy_detach(spy, chan); + } else + ast_mutex_unlock(&spy->lock); } + AST_LIST_TRAVERSE_SAFE_END + spy_cleanup(chan); } void ast_channel_spy_trigger_wait(struct ast_channel_spy *spy) @@ -1049,65 +1086,59 @@ void ast_channel_spy_trigger_wait(struct ast_channel_spy *spy) void ast_channel_spy_remove(struct ast_channel *chan, struct ast_channel_spy *spy) { - struct ast_frame *f; - if (!chan->spies) return; AST_LIST_REMOVE(&chan->spies->list, spy, list); - ast_mutex_lock(&spy->lock); + spy_detach(spy, chan); + spy_cleanup(chan); +} - spy->chan = NULL; +void ast_channel_spy_free(struct ast_channel_spy *spy) +{ + struct ast_frame *f = NULL; - for (f = spy->read_queue.head; f; f = spy->read_queue.head) { - spy->read_queue.head = f->next; - ast_frfree(f); - } + if (spy->status == CHANSPY_DONE) + return; + + /* Switch status to done in case we get called twice */ + spy->status = CHANSPY_DONE; + + /* Drop any frames in the queue */ for (f = spy->write_queue.head; f; f = spy->write_queue.head) { spy->write_queue.head = f->next; ast_frfree(f); } + for (f = spy->read_queue.head; f; f= spy->read_queue.head) { + spy->read_queue.head = f->next; + ast_frfree(f); + } + /* Destroy the condition if in use */ if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) ast_cond_destroy(&spy->trigger); - ast_mutex_unlock(&spy->lock); - - ast_log(LOG_DEBUG, "Spy %s removed from channel %s\n", - spy->type, chan->name); + /* Destroy our mutex since it is no longer in use */ + ast_mutex_destroy(&spy->lock); - if (AST_LIST_EMPTY(&chan->spies->list)) { - if (chan->spies->read_translator.path) - ast_translator_free_path(chan->spies->read_translator.path); - if (chan->spies->write_translator.path) - ast_translator_free_path(chan->spies->write_translator.path); - free(chan->spies); - chan->spies = NULL; - } + return; } static void detach_spies(struct ast_channel *chan) { - struct ast_channel_spy *spy; + struct ast_channel_spy *spy = NULL; if (!chan->spies) return; - /* Marking the spies as done is sufficient. Chanspy or spy users will get the picture. */ - AST_LIST_TRAVERSE(&chan->spies->list, spy, list) { - ast_mutex_lock(&spy->lock); - spy->chan = NULL; - if (spy->status == CHANSPY_RUNNING) - spy->status = CHANSPY_DONE; - if (ast_test_flag(spy, CHANSPY_TRIGGER_MODE) != CHANSPY_TRIGGER_NONE) - ast_cond_signal(&spy->trigger); - ast_mutex_unlock(&spy->lock); + AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) { + AST_LIST_REMOVE_CURRENT(&chan->spies->list, list); + spy_detach(spy, chan); } + AST_LIST_TRAVERSE_SAFE_END - AST_LIST_TRAVERSE_SAFE_BEGIN(&chan->spies->list, spy, list) - ast_channel_spy_remove(chan, spy); - AST_LIST_TRAVERSE_SAFE_END; + spy_cleanup(chan); } /*--- ast_softhangup_nolock: Softly hangup a channel, don't lock */ diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 5259a459f..d217ba81c 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2447,7 +2447,7 @@ static int sip_hangup(struct ast_channel *ast) { struct sip_pvt *p = ast->tech_pvt; int needcancel = 0; - struct ast_flags locflags = {0}; + int needdestroy = 0; if (!p) { ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n"); @@ -2481,7 +2481,6 @@ static int sip_hangup(struct ast_channel *ast) #endif /* Disconnect */ - p = ast->tech_pvt; if (p->vad) { ast_dsp_free(p->vad); } @@ -2493,7 +2492,16 @@ static int sip_hangup(struct ast_channel *ast) ast_mutex_unlock(&usecnt_lock); ast_update_use_count(); - ast_set_flag(&locflags, SIP_NEEDDESTROY); + /* Do not destroy this pvt until we have timeout or + get an answer to the BYE or INVITE/CANCEL + If we get no answer during retransmit period, drop the call anyway. + (Sorry, mother-in-law, you can't deny a hangup by sending + 603 declined to BYE...) + */ + if (ast_test_flag(p, SIP_ALREADYGONE)) + needdestroy = 1; /* Set destroy flag at end of this function */ + else + sip_scheddestroy(p, 32000); /* Start the process if it's not already started */ if (!ast_test_flag(p, SIP_ALREADYGONE) && !ast_strlen_zero(p->initreq.data)) { @@ -2506,13 +2514,12 @@ static int sip_hangup(struct ast_channel *ast) it pending */ if (!ast_test_flag(p, SIP_CAN_BYE)) { ast_set_flag(p, SIP_PENDINGBYE); + /* Do we need a timer here if we don't hear from them at all? */ } else { /* Send a new request: CANCEL */ transmit_request_with_auth(p, SIP_CANCEL, p->ocseq, 1, 0); /* Actually don't destroy us yet, wait for the 487 on our original INVITE, but do set an autodestruct just in case we never get it. */ - ast_clear_flag(&locflags, SIP_NEEDDESTROY); - sip_scheddestroy(p, 32000); } if ( p->initid != -1 ) { /* channel still up - reverse dec of inUse counter @@ -2538,7 +2545,8 @@ static int sip_hangup(struct ast_channel *ast) } } } - ast_copy_flags(p, (&locflags), SIP_NEEDDESTROY); + if (needdestroy) + ast_set_flag(p, SIP_NEEDDESTROY); ast_mutex_unlock(&p->lock); return 0; } @@ -10085,6 +10093,9 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ handle_response_invite(p, resp, rest, req, ignore, seqno); } else if (sipmethod == SIP_REGISTER) { res = handle_response_register(p, resp, rest, req, ignore, seqno); + } else if (sipmethod == SIP_BYE) { + /* Ok, we're ready to go */ + ast_set_flag(p, SIP_NEEDDESTROY); } break; case 401: /* Not www-authorized on SIP method */ @@ -10236,9 +10247,12 @@ static void handle_response(struct sip_pvt *p, int resp, char *rest, struct sip_ handle_response_invite(p, resp, rest, req, ignore, seqno); } else if (sipmethod == SIP_CANCEL) { ast_log(LOG_DEBUG, "Got 200 OK on CANCEL\n"); - } else if (sipmethod == SIP_MESSAGE) + } else if (sipmethod == SIP_MESSAGE) /* We successfully transmitted a message */ ast_set_flag(p, SIP_NEEDDESTROY); + else if (sipmethod == SIP_BYE) + /* Ok, we're ready to go */ + ast_set_flag(p, SIP_NEEDDESTROY); break; case 401: /* www-auth */ case 407: @@ -10924,10 +10938,15 @@ static int handle_request_bye(struct sip_pvt *p, struct sip_request *req, int de if (p->owner) ast_queue_hangup(p->owner); } - } else if (p->owner) + } else if (p->owner) { ast_queue_hangup(p->owner); - else + if (option_debug > 2) + ast_log(LOG_DEBUG, "Received bye, issuing owner hangup\n."); + } else { ast_set_flag(p, SIP_NEEDDESTROY); + if (option_debug > 2) + ast_log(LOG_DEBUG, "Received bye, no owner, selfdestruct soon.\n."); + } transmit_response(p, "200 OK", req); return 1; @@ -13057,24 +13076,26 @@ static int sip_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp, struc if (!p) return -1; ast_mutex_lock(&p->lock); - if (rtp) { + if (rtp) { changed |= ast_rtp_get_peer(rtp, &p->redirip); #ifdef SIP_MIDCOM if (m_cb) - m_cb->ast_rtp_get_their_nat_audio_hook(rtp, p->r); + m_cb->ast_rtp_get_their_nat_audio_hook(rtp, p->r); #endif - } - else + } else if (p->redirip.sin_addr.s_addr || ntohs(p->redirip.sin_port) != 0) { memset(&p->redirip, 0, sizeof(p->redirip)); - if (vrtp) { + changed = 1; + } + if (vrtp) { changed |= ast_rtp_get_peer(vrtp, &p->vredirip); #ifdef SIP_MIDCOM if (m_cb) - m_cb->ast_rtp_get_their_nat_video_hook(vrtp, p->r); + m_cb->ast_rtp_get_their_nat_video_hook(vrtp, p->r); #endif - } - else + } else if (p->vredirip.sin_addr.s_addr || ntohs(p->vredirip.sin_port) != 0) { memset(&p->vredirip, 0, sizeof(p->vredirip)); + changed = 1; + } if (codecs && (p->redircodecs != codecs)) { p->redircodecs = codecs; changed = 1; diff --git a/configs/zapata.conf.sample b/configs/zapata.conf.sample index 6bad849d3..8038f8995 100644 --- a/configs/zapata.conf.sample +++ b/configs/zapata.conf.sample @@ -16,7 +16,7 @@ ; Trunk groups are used for NFAS or GR-303 connections. ; ; Group: Defines a trunk group. -; group => <trunkgroup>,<dchannel>[,<backup1>...] +; trunkgroup => <trunkgroup>,<dchannel>[,<backup1>...] ; ; trunkgroup is the numerical trunk group to create ; dchannel is the zap channel which will have the diff --git a/include/asterisk/chanspy.h b/include/asterisk/chanspy.h index dcdceccf7..c6a64f592 100644 --- a/include/asterisk/chanspy.h +++ b/include/asterisk/chanspy.h @@ -95,6 +95,15 @@ int ast_channel_spy_add(struct ast_channel *chan, struct ast_channel_spy *spy); void ast_channel_spy_remove(struct ast_channel *chan, struct ast_channel_spy *spy); /*! + \brief Free a spy. + \param spy The spy to free + \return nothing + + Note: This function MUST NOT be called with the spy locked. +*/ +void ast_channel_spy_free(struct ast_channel_spy *spy); + +/*! \brief Find all spies of a particular type on a channel and stop them. \param chan The channel to operate on \param type A character string identifying the type of spies to be stopped |