summaryrefslogtreecommitdiff
path: root/channels/chan_skinny.c
diff options
context:
space:
mode:
authorDamien Wedhorn <voip@facts.com.au>2013-12-19 02:59:52 +0000
committerDamien Wedhorn <voip@facts.com.au>2013-12-19 02:59:52 +0000
commitc2fd229fbaf161ae91b87ca38845636089d96a4c (patch)
tree5c1a72240d35c89bee180d5cfcad2b70c6be69ba /channels/chan_skinny.c
parent7e9febbf86f7a9aa0cc1d9852d1ed1b77f25b3ce (diff)
Fixup some skinny bugs causing Fracks and ao2 cleanup issues.
Moved channel locking into setsubstate so that a process can complete working on a sub before another starts changing it. The existing code was causing some Fracks with schedule deletion. Removed multiple rtp cleanup. Now only cleansup up once, fixing ao2 object cleanup issues. ........ Merged revisions 404306 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404307 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels/chan_skinny.c')
-rw-r--r--channels/chan_skinny.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 9d04f2336..e54108c3b 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -2006,6 +2006,20 @@ static struct ast_variable *add_var(const char *buf, struct ast_variable *list)
return list;
}
+static void skinny_locksub(struct skinny_subchannel *sub)
+{
+ if (sub && sub->owner) {
+ ast_channel_lock(sub->owner);
+ }
+}
+
+static void skinny_unlocksub(struct skinny_subchannel *sub)
+{
+ if (sub && sub->owner) {
+ ast_channel_unlock(sub->owner);
+ }
+}
+
static int skinny_sched_del(int sched_id, struct skinny_subchannel *sub)
{
SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Deleting SCHED %d\n",
@@ -4921,8 +4935,10 @@ static int skinny_dialer_cb(const void *data)
static int skinny_autoanswer_cb(const void *data)
{
struct skinny_subchannel *sub = (struct skinny_subchannel *)data;
+ skinny_locksub(sub);
sub->aa_sched = 0;
setsubstate(sub, SKINNY_CONNECTED);
+ skinny_unlocksub(sub);
return 0;
}
@@ -4969,6 +4985,7 @@ static int skinny_call(struct ast_channel *ast, const char *dest, int timeout)
return -1;
}
+ skinny_locksub(sub);
AST_LIST_TRAVERSE(ast_channel_varshead(ast), current, entries) {
if (!(strcmp(ast_var_name(current), "SKINNY_AUTOANSWER"))) {
if (d->hookstate == SKINNY_ONHOOK && !sub->aa_sched) {
@@ -5001,6 +5018,7 @@ static int skinny_call(struct ast_channel *ast, const char *dest, int timeout)
if (doautoanswer) {
setsubstate(sub, SUBSTATE_CONNECTED);
}
+ skinny_unlocksub(sub);
return res;
}
@@ -5573,6 +5591,8 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
return;
}
+ skinny_locksub(sub);
+
if (sub->dialer_sched) {
skinny_sched_del(sub->dialer_sched, sub);
sub->dialer_sched = 0;
@@ -5590,6 +5610,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
if (skinny_sched_del(sub->cfwd_sched, sub)) {
SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - trying to change state from %s to %s, but already forwarded because no answer.\n",
sub->callid, substate2str(sub->substate), substate2str(actualstate));
+ skinny_unlocksub(sub);
return;
}
sub->cfwd_sched = 0;
@@ -5666,12 +5687,11 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
sub->cxmode = SKINNY_CX_RECVONLY;
sub->substate = SUBSTATE_ONHOOK;
- destroy_rtp(sub);
sub->substate = SUBSTATE_ONHOOK;
if (sub->owner) {
ast_queue_hangup(sub->owner);
}
- return;
+ break;
case SUBSTATE_CONNECTED:
transmit_activatecallplane(d, l);
transmit_stop_tone(d, l->instance, sub->callid);
@@ -5691,7 +5711,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
}
sub->substate = SUBSTATE_CONNECTED;
l->activesub = sub;
- return;
+ break;
case SUBSTATE_HOLD:
if (sub->substate != SUBSTATE_CONNECTED) {
ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
@@ -5709,10 +5729,12 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
ast_queue_hold(sub->owner, l->mohsuggest);
- return;
+ break;
default:
ast_log(LOG_WARNING, "Substate handling under subline for state %d not implemented on Sub-%d\n", state, sub->callid);
}
+ skinny_unlocksub(sub);
+ return;
}
if ((d->hookstate == SKINNY_ONHOOK) && ((actualstate == SUBSTATE_OFFHOOK) || (actualstate == SUBSTATE_DIALING)
@@ -5726,6 +5748,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
sub->callid, substate2str(sub->substate), substate2str(actualstate));
if (actualstate == sub->substate) {
+ skinny_unlocksub(sub);
return;
}
@@ -5766,10 +5789,10 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
}
sub->cxmode = SKINNY_CX_RECVONLY;
- destroy_rtp(sub);
if (sub->owner) {
if (sub->substate == SUBSTATE_OFFHOOK) {
sub->substate = SUBSTATE_ONHOOK;
+ skinny_unlocksub(sub);
ast_hangup(sub->owner);
} else {
sub->substate = SUBSTATE_ONHOOK;
@@ -5782,7 +5805,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_DIALING:
if (ast_strlen_zero(sub->exten) || !ast_exists_extension(c, ast_channel_context(c), sub->exten, 1, l->cid_num)) {
ast_log(LOG_WARNING, "Exten (%s)@(%s) does not exist, unable to set substate DIALING on sub %d\n", sub->exten, ast_channel_context(c), sub->callid);
- return;
+ break;
}
if (d->hookstate == SKINNY_ONHOOK) {
@@ -5825,7 +5848,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_RINGOUT:
if (!(sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_PROGRESS)) {
ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_RINGOUT from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
- return;
+ break;
}
if (sub->substate != SUBSTATE_PROGRESS) {
transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS);
@@ -5923,7 +5946,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_BUSY:
if (!(sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_PROGRESS || sub->substate == SUBSTATE_RINGOUT)) {
ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_BUSY from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
- return;
+ break;
}
if (!d->earlyrtp) {
@@ -5937,7 +5960,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_CONGESTION:
if (!(sub->substate == SUBSTATE_DIALING || sub->substate == SUBSTATE_PROGRESS || sub->substate == SUBSTATE_RINGOUT)) {
ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_CONGESTION from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
- return;
+ break;
}
if (!d->earlyrtp) {
@@ -5951,7 +5974,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_PROGRESS:
if (sub->substate != SUBSTATE_DIALING) {
ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_PROGRESS from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
- return;
+ break;
}
if (!d->earlyrtp) {
@@ -5965,7 +5988,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
case SUBSTATE_HOLD:
if (sub->substate != SUBSTATE_CONNECTED) {
ast_log(LOG_WARNING, "Cannot set substate to SUBSTATE_HOLD from %s (on call-%d)\n", substate2str(sub->substate), sub->callid);
- return;
+ break;
}
ast_queue_hold(sub->owner, l->mohsuggest);
@@ -5981,6 +6004,7 @@ static void setsubstate(struct skinny_subchannel *sub, int state)
default:
ast_log(LOG_WARNING, "Was asked to change to nonexistant substate %d on Sub-%d\n", state, sub->callid);
}
+ skinny_unlocksub(sub);
}
static void dumpsub(struct skinny_subchannel *sub, int forcehangup)
@@ -6042,8 +6066,6 @@ static void activatesub(struct skinny_subchannel *sub, int state)
SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d - Activating, and deactivating sub %d\n",
sub->callid, l->activesub ? l->activesub->callid : 0);
- ast_channel_lock(sub->owner);
-
if (sub == l->activesub) {
setsubstate(sub, state);
} else {
@@ -6057,8 +6079,6 @@ static void activatesub(struct skinny_subchannel *sub, int state)
l->activesub = sub;
setsubstate(sub, state);
}
-
- ast_channel_unlock(sub->owner);
}
static void dialandactivatesub(struct skinny_subchannel *sub, char exten[AST_MAX_EXTENSION])