diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index 8bbf9e97b8..b6f91f7c65 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -2246,6 +2246,13 @@ static void my_set_pulsedial(void *pvt, int flag) p->pulsedial = flag; } +static void my_set_new_owner(void *pvt, struct ast_channel *new_owner) +{ + struct dahdi_pvt *p = pvt; + + p->owner = new_owner; +} + static const char *my_get_orig_dialstring(void *pvt) { struct dahdi_pvt *p = pvt; @@ -3528,6 +3535,7 @@ static struct analog_callback dahdi_analog_callbacks = .cancel_cidspill = my_cancel_cidspill, .confmute = my_confmute, .set_pulsedial = my_set_pulsedial, + .set_new_owner = my_set_new_owner, .get_orig_dialstring = my_get_orig_dialstring, .set_needringing = my_set_needringing, .set_polarity = my_set_polarity, diff --git a/channels/sig_analog.c b/channels/sig_analog.c index 6788b83092..ba6ed45c8e 100644 --- a/channels/sig_analog.c +++ b/channels/sig_analog.c @@ -412,6 +412,14 @@ static int analog_play_tone(struct analog_pvt *p, enum analog_sub sub, enum anal return -1; } +static void analog_set_new_owner(struct analog_pvt *p, struct ast_channel *new_owner) +{ + p->owner = new_owner; + if (p->calls->set_new_owner) { + p->calls->set_new_owner(p->chan_pvt, new_owner); + } +} + static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor) { struct ast_channel *c; @@ -426,7 +434,7 @@ static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int sta } p->subs[sub].owner = c; if (!p->owner) { - p->owner = c; + analog_set_new_owner(p, c); } return c; } @@ -1290,7 +1298,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) /* Move to the call-wait, but un-own us until they flip back. */ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL); analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT); - p->owner = NULL; + analog_set_new_owner(p, NULL); } else { /* The three way hung up, but we still have a call wait */ ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n"); @@ -1301,11 +1309,11 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) another call */ ast_debug(1, "Call was complete, setting owner to former third call\n"); analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); } else { /* This call hasn't been completed yet... Set owner to NULL */ ast_debug(1, "Call was incomplete, setting owner to NULL\n"); - p->owner = NULL; + analog_set_new_owner(p, NULL); } } } else if (p->subs[ANALOG_SUB_CALLWAIT].allocd) { @@ -1313,14 +1321,14 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) analog_lock_sub_owner(p, ANALOG_SUB_CALLWAIT); if (!p->subs[ANALOG_SUB_CALLWAIT].owner) { /* The call waiting call dissappeared. */ - p->owner = NULL; + analog_set_new_owner(p, NULL); break; } /* Move to the call-wait and switch back to them. */ analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL); analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); if (p->owner->_state != AST_STATE_UP) { ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER); } @@ -1337,11 +1345,11 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) another call */ ast_debug(1, "Call was complete, setting owner to former third call\n"); analog_set_inthreeway(p, ANALOG_SUB_REAL, 0); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); } else { /* This call hasn't been completed yet... Set owner to NULL */ ast_debug(1, "Call was incomplete, setting owner to NULL\n"); - p->owner = NULL; + analog_set_new_owner(p, NULL); } } break; @@ -1402,7 +1410,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast) } if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) { - p->owner = NULL; + analog_set_new_owner(p, NULL); analog_set_ringtimeout(p, 0); analog_set_confirmanswer(p, 0); analog_set_pulsedial(p, 0); @@ -1512,7 +1520,7 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast) ast_debug(1, "Finally swapping real and threeway\n"); analog_play_tone(p, ANALOG_SUB_THREEWAY, -1); analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); } } @@ -2252,7 +2260,7 @@ static void *__analog_ss_thread(void *data) } analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY); analog_unalloc_sub(p, ANALOG_SUB_THREEWAY); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) { ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD); } @@ -2264,7 +2272,7 @@ static void *__analog_ss_thread(void *data) analog_play_tone(p, idx, -1); analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY); analog_unalloc_sub(p, ANALOG_SUB_THREEWAY); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); ast_hangup(chan); goto quit; } @@ -2744,7 +2752,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel); analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT); analog_stop_callwait(p); - p->owner = NULL; + analog_set_new_owner(p, NULL); /* Don't start streaming audio yet if the incoming call isn't up yet */ if (p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP) { analog_set_dialing(p, 1); @@ -2794,7 +2802,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); /* Unlock the 3-way call that we swapped to real-call. */ ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner); - p->owner = NULL; + analog_set_new_owner(p, NULL); /* Ring the phone */ analog_ring(p); } else { @@ -2817,7 +2825,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); /* Unlock the 3-way call that we swapped to real-call. */ ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner); - p->owner = NULL; + analog_set_new_owner(p, NULL); /* Ring the phone */ analog_ring(p); } @@ -3064,7 +3072,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ /* Swap to call-wait */ analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_CALLWAIT); analog_play_tone(p, ANALOG_SUB_REAL, -1); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); ast_debug(1, "Making %s the new owner\n", p->owner->name); if (p->subs[ANALOG_SUB_REAL].owner->_state == AST_STATE_RINGING) { ast_setstate(p->subs[ANALOG_SUB_REAL].owner, AST_STATE_UP); @@ -3149,7 +3157,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ if (res) { ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel); } - p->ss_astchan = p->owner = chan; + analog_set_new_owner(p, chan); + p->ss_astchan = chan; if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, p)) { ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel); res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION); @@ -3191,7 +3200,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ /* Swap back -- we're dropping the real 3-way that isn't finished yet*/ analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); orig_3way_sub = ANALOG_SUB_REAL; - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); } /* Drop the last call and stop the conference */ ast_verb(3, "Dropping three-way call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name); @@ -3215,13 +3224,13 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_ if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) { ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD); } - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); } else { ast_verb(3, "Dumping incomplete call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name); analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL); orig_3way_sub = ANALOG_SUB_REAL; ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) { ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD); } @@ -3457,7 +3466,7 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast if ((res != ANALOG_EVENT_RINGEROFF) && (res != ANALOG_EVENT_RINGERON) && (res != ANALOG_EVENT_HOOKCOMPLETE)) { ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res); - p->owner = p->subs[ANALOG_SUB_REAL].owner; + analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner); if (p->owner && ast != p->owner) { /* * Could this even happen? @@ -3834,7 +3843,7 @@ int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void int x; ast_debug(1, "New owner for channel %d is %s\n", new_pvt->channel, newchan->name); if (new_pvt->owner == oldchan) { - new_pvt->owner = newchan; + analog_set_new_owner(new_pvt, newchan); } for (x = 0; x < 3; x++) { if (new_pvt->subs[x].owner == oldchan) { diff --git a/channels/sig_analog.h b/channels/sig_analog.h index 3c33aebf04..d7b6011a39 100644 --- a/channels/sig_analog.h +++ b/channels/sig_analog.h @@ -231,6 +231,7 @@ struct analog_callback { void (* const cancel_cidspill)(void *pvt); int (* const confmute)(void *pvt, int mute); void (* const set_pulsedial)(void *pvt, int flag); + void (* const set_new_owner)(void *pvt, struct ast_channel *new_owner); const char *(* const get_orig_dialstring)(void *pvt); };