[asterisk-commits] rmudgett: branch 1.6.2 r318735 - in /branches/1.6.2: ./ apps/ channels/ inclu...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu May 12 20:14:42 CDT 2011
Author: rmudgett
Date: Thu May 12 20:14:28 2011
New Revision: 318735
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=318735
Log:
Merged revisions 318734 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
................
r318734 | rmudgett | 2011-05-12 20:09:40 -0500 (Thu, 12 May 2011) | 43 lines
Merged revisions 318671 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8
* The applicable fixes for v1.4 are the SIP deadlock and the in progress
masquerade check for multiple parties trying to pickup the same call.
issue18654_v1.4.patch uploaded by rmudgett (license 664)
* Backported to v1.6.2.
issue18654_v1.6.2.patch uploaded by rmudgett (license 664)
........
r318671 | alecdavis | 2011-05-13 10:52:08 +1200 (Fri, 13 May 2011) | 30 lines
Fix directed group pickup feature code *8 with pickupsounds enabled
Since 1.6.2, the new pickupsound and pickupfailsound in features.conf cause many issues.
1). chan_sip:handle_request_invite() shouldn't be playing out the fail/success audio, as it has 'netlock' locked.
2). dialplan applications for directed_pickups shouldn't beep.
3). feature code for directed pickup should beep on success/failure if configured.
Created a sip_pickup() thread to handle the pickup and playout the audio, spawned from handle_request_invite.
Moved app_directed:pickup_do() to features:ast_do_pickup().
Functions below, all now use the new ast_do_pickup()
app_directed_pickup.c:
pickup_by_channel()
pickup_by_exten()
pickup_by_mark()
pickup_by_part()
features.c:
ast_pickup_call()
(closes issue #18654)
Reported by: Docent
Patches:
ast_do_pickup_1.8_trunk.diff.txt uploaded by alecdavis (license 585)
Tested by: lmadsen, francesco_r, amilcar, isis242, alecdavis, irroot, rymkus, loloski, rmudgett
Review: https://reviewboard.asterisk.org/r/1185/
........
................
Modified:
branches/1.6.2/ (props changed)
branches/1.6.2/apps/app_directed_pickup.c
branches/1.6.2/channels/chan_sip.c
branches/1.6.2/include/asterisk/features.h
branches/1.6.2/main/features.c
Propchange: branches/1.6.2/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.
Modified: branches/1.6.2/apps/app_directed_pickup.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.2/apps/app_directed_pickup.c?view=diff&rev=318735&r1=318734&r2=318735
==============================================================================
--- branches/1.6.2/apps/app_directed_pickup.c (original)
+++ branches/1.6.2/apps/app_directed_pickup.c Thu May 12 20:14:28 2011
@@ -87,38 +87,17 @@
static const char *app2 = "PickupChan";
/*! \todo This application should return a result code, like PICKUPRESULT */
-/* Perform actual pickup between two channels */
-static int pickup_do(struct ast_channel *chan, struct ast_channel *target)
-{
- int res = 0;
-
- ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
-
- if ((res = ast_answer(chan))) {
- ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
- return -1;
- }
-
- if ((res = ast_queue_control(chan, AST_CONTROL_ANSWER))) {
- ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
- return -1;
- }
-
- if ((res = ast_channel_masquerade(target, chan))) {
- ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
- return -1;
- }
-
- return res;
-}
-
/* Helper function that determines whether a channel is capable of being picked up */
static int can_pickup(struct ast_channel *chan)
{
- if (!chan->pbx && (chan->_state == AST_STATE_RINGING || chan->_state == AST_STATE_RING || chan->_state == AST_STATE_DOWN))
+ if (!chan->pbx && !chan->masq &&
+ !ast_test_flag(chan, AST_FLAG_ZOMBIE) &&
+ (chan->_state == AST_STATE_RINGING ||
+ chan->_state == AST_STATE_RING ||
+ chan->_state == AST_STATE_DOWN)) {
return 1;
- else
- return 0;
+ }
+ return 0;
}
/*! \brief Helper Function to walk through ALL channels checking NAME and STATE */
@@ -169,8 +148,8 @@
return -1;
/* Just check that we are not picking up the SAME as target */
- if (chan->name != target->name && chan != target) {
- res = pickup_do(chan, target);
+ if (chan != target) {
+ res = ast_do_pickup(chan, target);
}
ast_channel_unlock(target);
@@ -205,9 +184,8 @@
target = ast_channel_search_locked(find_by_exten, &search);
if (target) {
- int res = pickup_do(chan, target);
+ int res = ast_do_pickup(chan, target);
ast_channel_unlock(target);
- target = NULL;
return res;
}
@@ -230,9 +208,31 @@
struct ast_channel *target = ast_channel_search_locked(find_by_mark, (char *) mark);
if (target) {
- int res = pickup_do(chan, target);
+ int res = ast_do_pickup(chan, target);
ast_channel_unlock(target);
- target = NULL;
+ return res;
+ }
+
+ return -1;
+}
+
+static int find_by_group(struct ast_channel *c, void *data)
+{
+ struct ast_channel *chan = data;
+
+ return (c != chan) && (chan->pickupgroup & c->callgroup) && can_pickup(c);
+}
+
+static int pickup_by_group(struct ast_channel *chan)
+{
+ struct ast_channel *target = ast_channel_search_locked(find_by_group, chan);
+
+ if (target) {
+ int res;
+
+ ast_log(LOG_NOTICE, "%s, pickup attempt by %s\n", target->name, chan->name);
+ res = ast_do_pickup(chan, target);
+ ast_channel_unlock(target);
return res;
}
@@ -247,10 +247,10 @@
char *exten = NULL, *context = NULL;
if (ast_strlen_zero(data)) {
- res = ast_pickup_call(chan);
+ res = pickup_by_group(chan);
return res;
}
-
+
/* Parse extension (and context if there) */
while (!ast_strlen_zero(tmp) && (exten = strsep(&tmp, "&"))) {
if ((context = strchr(exten, '@')))
Modified: branches/1.6.2/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.2/channels/chan_sip.c?view=diff&rev=318735&r1=318734&r2=318735
==============================================================================
--- branches/1.6.2/channels/chan_sip.c (original)
+++ branches/1.6.2/channels/chan_sip.c Thu May 12 20:14:28 2011
@@ -2339,6 +2339,10 @@
static void check_pendings(struct sip_pvt *p);
static void *sip_park_thread(void *stuff);
static int sip_park(struct ast_channel *chan1, struct ast_channel *chan2, struct sip_request *req, int seqno);
+
+static void *sip_pickup_thread(void *stuff);
+static int sip_pickup(struct ast_channel *chan);
+
static int sip_sipredirect(struct sip_pvt *p, const char *dest);
/*--- Codec handling / SDP */
@@ -19526,6 +19530,41 @@
return 0;
}
+
+/*! \brief SIP pickup support function
+ * Starts in a new thread, then pickup the call
+ */
+static void *sip_pickup_thread(void *stuff)
+{
+ struct ast_channel *chan;
+ chan = stuff;
+
+ if (ast_pickup_call(chan)) {
+ chan->hangupcause = AST_CAUSE_CALL_REJECTED;
+ } else {
+ chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ }
+ ast_hangup(chan);
+ chan = NULL;
+ return NULL;
+}
+
+/*! \brief Pickup a call using the subsystem in features.c
+ * This is executed in a separate thread
+ */
+static int sip_pickup(struct ast_channel *chan)
+{
+ pthread_t threadid;
+
+ if (ast_pthread_create_detached_background(&threadid, NULL, sip_pickup_thread, chan)) {
+ ast_debug(1, "Unable to start Group pickup thread on channel %s\n", chan->name);
+ return -1;
+ }
+ ast_debug(1, "Started Group pickup thread on channel %s\n", chan->name);
+ return 0;
+}
+
+
/*! \brief Turn off generator data
XXX Does this function belong in the SIP channel?
*/
@@ -20239,7 +20278,7 @@
return sip_uri_params_cmp(params1, params2);
}
-/* \note No channel or pvt locks should be held while calling this function. */
+/*! \note No channel or pvt locks should be held while calling this function. */
static int do_magic_pickup(struct ast_channel *channel, const char *extension, const char *context)
{
struct ast_str *str = ast_str_alloca(AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2);
@@ -20980,30 +21019,29 @@
/* Unlock locks so ast_hangup can do its magic */
ast_channel_unlock(c);
+ *nounlock = 1;
sip_pvt_unlock(p);
ast_hangup(c);
sip_pvt_lock(p);
c = NULL;
}
} else { /* Pickup call in call group */
- ast_channel_unlock(c);
- *nounlock = 1;
- if (ast_pickup_call(c)) {
- ast_log(LOG_NOTICE, "Nothing to pick up for %s\n", p->callid);
- transmit_response_reliable(p, "503 Unavailable", req);
+ if (sip_pickup(c)) {
+ ast_log(LOG_WARNING, "Failed to start Group pickup by %s\n", c->name);
+ transmit_response_reliable(p, "480 Temporarily Unavailable", req);
sip_alreadygone(p);
+ c->hangupcause = AST_CAUSE_FAILURE;
+
/* Unlock locks so ast_hangup can do its magic */
+ ast_channel_unlock(c);
+ *nounlock = 1;
+
+ p->invitestate = INV_COMPLETED;
sip_pvt_unlock(p);
- c->hangupcause = AST_CAUSE_CALL_REJECTED;
- } else {
- sip_pvt_unlock(p);
- ast_setstate(c, AST_STATE_DOWN);
- c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ ast_hangup(c);
+ sip_pvt_lock(p);
+ c = NULL;
}
- p->invitestate = INV_COMPLETED;
- ast_hangup(c);
- sip_pvt_lock(p);
- c = NULL;
}
break;
case AST_STATE_RING:
Modified: branches/1.6.2/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.2/include/asterisk/features.h?view=diff&rev=318735&r1=318734&r2=318735
==============================================================================
--- branches/1.6.2/include/asterisk/features.h (original)
+++ branches/1.6.2/include/asterisk/features.h Thu May 12 20:14:28 2011
@@ -120,6 +120,14 @@
/*! \brief Pickup a call */
int ast_pickup_call(struct ast_channel *chan);
+/*!
+ * \brief Pickup a call target
+ * \note This function assumes that target is locked
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target);
+
/*! \brief register new feature into feature_set
\param feature an ast_call_feature object which contains a keysequence
and a callback function which is called when this keysequence is pressed
Modified: branches/1.6.2/main/features.c
URL: http://svnview.digium.com/svn/asterisk/branches/1.6.2/main/features.c?view=diff&rev=318735&r1=318734&r2=318735
==============================================================================
--- branches/1.6.2/main/features.c (original)
+++ branches/1.6.2/main/features.c Thu May 12 20:14:28 2011
@@ -5044,17 +5044,19 @@
return 0;
}
-static int find_channel_by_group(struct ast_channel *c, void *data) {
+static int find_channel_by_group(struct ast_channel *c, void *data)
+{
struct ast_channel *chan = data;
return !c->pbx &&
/* Accessing 'chan' here is safe without locking, because there is no way for
- the channel do disappear from under us at this point. pickupgroup *could*
+ the channel to disappear from under us at this point. pickupgroup *could*
change while we're here, but that isn't a problem. */
(c != chan) &&
(chan->pickupgroup & c->callgroup) &&
((c->_state == AST_STATE_RINGING) || (c->_state == AST_STATE_RING)) &&
- !c->masq;
+ !c->masq &&
+ !ast_test_flag(c, AST_FLAG_ZOMBIE);
}
/*!
@@ -5064,35 +5066,62 @@
* Walk list of channels, checking it is not itself, channel is pbx one,
* check that the callgroup for both channels are the same and the channel is ringing.
* Answer calling channel, flag channel as answered on queue, masq channels together.
-*/
+ */
int ast_pickup_call(struct ast_channel *chan)
{
- struct ast_channel *cur = ast_channel_search_locked(find_channel_by_group, chan);
-
- if (cur) {
- int res = -1;
- ast_debug(1, "Call pickup on chan '%s' by '%s'\n",cur->name, chan->name);
- res = ast_answer(chan);
- if (res)
- ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
- res = ast_queue_control(chan, AST_CONTROL_ANSWER);
- if (res)
- ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
- res = ast_channel_masquerade(cur, chan);
- if (res)
- ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, cur->name); /* Done */
- if (!ast_strlen_zero(pickupsound)) {
- ast_stream_and_wait(cur, pickupsound, "");
- }
- ast_channel_unlock(cur);
- return res;
- } else {
- ast_debug(1, "No call pickup possible...\n");
+ struct ast_channel *target = ast_channel_search_locked(find_channel_by_group, chan);
+ int res = -1;
+ ast_debug(1, "pickup attempt by %s\n", chan->name);
+
+ if (target) {
+ if (!(res = ast_do_pickup(chan, target))) {
+ if (!ast_strlen_zero(pickupsound)) {
+ ast_stream_and_wait(target, pickupsound, "");
+ }
+ } else {
+ ast_log(LOG_WARNING, "pickup %s failed by %s\n", target->name, chan->name);
+ }
+ ast_channel_unlock(target);
+ }
+
+ if (res < 0) {
+ ast_debug(1, "No call pickup possible... for %s\n", chan->name);
if (!ast_strlen_zero(pickupfailsound)) {
+ ast_answer(chan);
ast_stream_and_wait(chan, pickupfailsound, "");
}
}
- return -1;
+
+ return res;
+}
+
+/*!
+ * \brief Pickup a call target, Common Code.
+ * \param chan channel that initiated pickup.
+ * \param target channel.
+ *
+ * Answer calling channel, flag channel as answered on queue, masq channels together.
+ */
+int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target)
+{
+ ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
+
+ if (ast_answer(chan)) {
+ ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan->name);
+ return -1;
+ }
+
+ if (ast_queue_control(chan, AST_CONTROL_ANSWER)) {
+ ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan->name);
+ return -1;
+ }
+
+ if (ast_channel_masquerade(target, chan)) {
+ ast_log(LOG_WARNING, "Unable to masquerade '%s' into '%s'\n", chan->name, target->name);
+ return -1;
+ }
+
+ return 0;
}
static char *app_bridge = "Bridge";
More information about the asterisk-commits
mailing list