aboutsummaryrefslogtreecommitdiffstats
path: root/apps/app_directed_pickup.c
diff options
context:
space:
mode:
authoralecdavis <alecdavis@f38db490-d61c-443f-a65b-d21fe96a405b>2011-05-12 22:56:43 +0000
committeralecdavis <alecdavis@f38db490-d61c-443f-a65b-d21fe96a405b>2011-05-12 22:56:43 +0000
commit26ed889533870367ecd4801485ecf4c0067c58a3 (patch)
tree0f9775a8aeaa78d0a6086971ea7aa08242a1bf82 /apps/app_directed_pickup.c
parente1c744fee83c55b506dd381e824eef992319aeb1 (diff)
Merged revisions 318671 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.8 ........ 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/ ........ git-svn-id: http://svn.digium.com/svn/asterisk/trunk@318672 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'apps/app_directed_pickup.c')
-rw-r--r--apps/app_directed_pickup.c125
1 files changed, 64 insertions, 61 deletions
diff --git a/apps/app_directed_pickup.c b/apps/app_directed_pickup.c
index 3914e0d8e..4ac81e578 100644
--- a/apps/app_directed_pickup.c
+++ b/apps/app_directed_pickup.c
@@ -97,60 +97,17 @@ static const char app[] = "Pickup";
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;
- struct ast_party_connected_line connected_caller;
- struct ast_channel *chans[2] = { chan, target };
-
- ast_debug(1, "Call pickup on '%s' by '%s'\n", target->name, chan->name);
- ast_cel_report_event(target, AST_CEL_PICKUP, NULL, NULL, chan);
-
- ast_party_connected_line_init(&connected_caller);
- ast_party_connected_line_copy(&connected_caller, &target->connected);
- connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- if (ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) {
- ast_channel_update_connected_line(chan, &connected_caller, NULL);
- }
- ast_party_connected_line_free(&connected_caller);
-
- ast_channel_lock(chan);
- ast_connected_line_copy_from_caller(&connected_caller, &chan->caller);
- ast_channel_unlock(chan);
- connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
- ast_channel_queue_connected_line_update(chan, &connected_caller, NULL);
- ast_party_connected_line_free(&connected_caller);
-
- 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;
- }
-
- /* If you want UniqueIDs, set channelvars in manager.conf to CHANNEL(uniqueid) */
- ast_manager_event_multichan(EVENT_FLAG_CALL, "Pickup", 2, chans,
- "Channel: %s\r\nTargetChannel: %s\r\n", chan->name, target->name);
-
- 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;
}
struct pickup_by_name_args {
@@ -213,9 +170,8 @@ static int pickup_by_channel(struct ast_channel *chan, char *pickup)
/* Just check that we are not picking up the SAME as target */
if (chan != target) {
- res = pickup_do(chan, target);
+ res = ast_do_pickup(chan, target);
}
-
ast_channel_unlock(target);
target = ast_channel_unref(target);
@@ -236,6 +192,7 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
while ((target = ast_channel_iterator_next(iter))) {
ast_channel_lock(target);
if ((chan != target) && can_pickup(target)) {
+ ast_log(LOG_NOTICE, "%s pickup by %s\n", target->name, chan->name);
break;
}
ast_channel_unlock(target);
@@ -245,7 +202,7 @@ static int pickup_by_exten(struct ast_channel *chan, const char *exten, const ch
ast_channel_iterator_destroy(iter);
if (target) {
- res = pickup_do(chan, target);
+ res = ast_do_pickup(chan, target);
ast_channel_unlock(target);
target = ast_channel_unref(target);
}
@@ -277,13 +234,55 @@ static int pickup_by_mark(struct ast_channel *chan, const char *mark)
struct ast_channel *target;
int res = -1;
- if ((target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
- ast_channel_lock(target);
- res = pickup_do(chan, target);
- ast_channel_unlock(target);
- target = ast_channel_unref(target);
+ if (!(target = ast_channel_callback(find_by_mark, NULL, (char *) mark, 0))) {
+ return res;
+ }
+
+ ast_channel_lock(target);
+ if (can_pickup(target)) {
+ res = ast_do_pickup(chan, target);
+ } else {
+ ast_log(LOG_WARNING, "target has gone, or not ringing anymore for %s\n", chan->name);
+ }
+ ast_channel_unlock(target);
+ target = ast_channel_unref(target);
+
+ return res;
+}
+
+static int find_channel_by_group(void *obj, void *arg, void *data, int flags)
+{
+ struct ast_channel *chan = obj;
+ struct ast_channel *c = data;
+ int i;
+
+ ast_channel_lock(chan);
+ i = (c != chan) && (c->pickupgroup & chan->callgroup) &&
+ can_pickup(chan);
+
+ ast_channel_unlock(chan);
+ return i ? CMP_MATCH | CMP_STOP : 0;
+}
+
+static int pickup_by_group(struct ast_channel *chan)
+{
+ struct ast_channel *target;
+ int res = -1;
+
+ if (!(target = ast_channel_callback(find_channel_by_group, NULL, chan, 0))) {
+ return res;
}
+ ast_log(LOG_NOTICE, "%s, pickup attempt by %s\n", target->name, chan->name);
+ ast_channel_lock(target);
+ if (can_pickup(target)) {
+ res = ast_do_pickup(chan, target);
+ } else {
+ ast_log(LOG_WARNING, "target has gone, or not ringing anymore for %s\n", chan->name);
+ }
+ ast_channel_unlock(target);
+ target = ast_channel_unref(target);
+
return res;
}
@@ -295,10 +294,10 @@ static int pickup_exec(struct ast_channel *chan, const char *data)
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, '@')))
@@ -341,7 +340,11 @@ static int pickup_by_part(struct ast_channel *chan, const char *part)
if ((target = ast_channel_callback(find_by_part, NULL, (char *) part, 0))) {
ast_channel_lock(target);
- res = pickup_do(chan, target);
+ if (can_pickup(target)) {
+ res = ast_do_pickup(chan, target);
+ } else {
+ ast_log(LOG_WARNING, "target has gone, or not ringing anymore for %s\n", chan->name);
+ }
ast_channel_unlock(target);
target = ast_channel_unref(target);
}