diff options
author | Alec L Davis <sivad.a@paradise.net.nz> | 2011-05-12 22:56:43 +0000 |
---|---|---|
committer | Alec L Davis <sivad.a@paradise.net.nz> | 2011-05-12 22:56:43 +0000 |
commit | 892b7a2efd3ed0f30850caa399f96530120db3dd (patch) | |
tree | 0f9775a8aeaa78d0a6086971ea7aa08242a1bf82 /apps/app_directed_pickup.c | |
parent | c37c017781e794916f657ec20afe887758484a6c (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: https://origsvn.digium.com/svn/asterisk/trunk@318672 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'apps/app_directed_pickup.c')
-rw-r--r-- | apps/app_directed_pickup.c | 125 |
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); } |