app_chanspy: Fix a bug where Barge mode could fail
authorJonathan Rose <jrose@digium.com>
Fri, 9 May 2014 17:03:41 +0000 (17:03 +0000)
committerJonathan Rose <jrose@digium.com>
Fri, 9 May 2014 17:03:41 +0000 (17:03 +0000)
If the barge audiohook was attached prior to the spyee and its peer
actually being bridged, the audiohook would not be applied and the
connected peer would not be able to hear audio from the spy when the
spy is in barge mode.

(closes issue ASTERISK-23381)
Reported by: Robert Moss
Review: https://reviewboard.asterisk.org/r/3505/
........

Merged revisions 413551 from http://svn.asterisk.org/svn/asterisk/branches/11
........

Merged revisions 413556 from http://svn.asterisk.org/svn/asterisk/branches/12

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@413557 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_chanspy.c

index f568083..987eacf 100644 (file)
@@ -593,12 +593,43 @@ static void publish_chanspy_message(struct ast_channel *spyer,
        stasis_publish(ast_channel_topic(spyer), message);
 }
 
+static int attach_barge(struct ast_autochan *spyee_autochan,
+       struct ast_autochan **spyee_bridge_autochan, struct ast_audiohook *bridge_whisper_audiohook,
+       const char *spyer_name, const char *name)
+{
+       int retval = 0;
+       struct ast_autochan *internal_bridge_autochan;
+       RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(spyee_autochan->chan), ast_channel_cleanup);
+
+       if (!bridged) {
+               return -1;
+       }
+
+       ast_audiohook_init(bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy", 0);
+
+       internal_bridge_autochan = ast_autochan_setup(bridged);
+       if (!internal_bridge_autochan) {
+               return -1;
+       }
+
+       ast_channel_lock(internal_bridge_autochan->chan);
+       if (start_spying(internal_bridge_autochan, spyer_name, bridge_whisper_audiohook)) {
+               ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee '%s'. Barge mode disabled.\n", name);
+               retval = -1;
+       }
+       ast_channel_unlock(internal_bridge_autochan->chan);
+
+       *spyee_bridge_autochan = internal_bridge_autochan;
+
+       return retval;
+}
+
 static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_autochan,
        int *volfactor, int fd, struct spy_dtmf_options *user_options, struct ast_flags *flags,
        char *exitcontext)
 {
        struct chanspy_translation_helper csth;
-       int running = 0, res, x = 0;
+       int running = 0, bridge_connected = 0, res, x = 0;
        char inp[24] = {0};
        char *name;
        struct ast_frame *f;
@@ -646,23 +677,6 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto
                }
        }
 
-       if (ast_test_flag(flags, OPTION_BARGE | OPTION_DTMF_SWITCH_MODES)) {
-               RAII_VAR(struct ast_channel *, bridged, ast_channel_bridge_peer(spyee_autochan->chan), ast_channel_cleanup);
-
-               /* And this hook lets us inject audio into the channel that the spied on
-                  channel is currently bridged with.
-               */
-               ast_audiohook_init(&csth.bridge_whisper_audiohook, AST_AUDIOHOOK_TYPE_WHISPER, "Chanspy", 0);
-
-               if ((spyee_bridge_autochan = ast_autochan_setup(bridged))) {
-                       ast_channel_lock(spyee_bridge_autochan->chan);
-                       if (start_spying(spyee_bridge_autochan, spyer_name, &csth.bridge_whisper_audiohook)) {
-                               ast_log(LOG_WARNING, "Unable to attach barge audiohook on spyee %s. Barge mode disabled!\n", name);
-                       }
-                       ast_channel_unlock(spyee_bridge_autochan->chan);
-               }
-       }
-
        ast_channel_lock(chan);
        ast_set_flag(ast_channel_flags(chan), AST_FLAG_END_DTMF_ONLY);
        ast_channel_unlock(chan);
@@ -702,6 +716,19 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto
                }
 
                if (ast_test_flag(flags, OPTION_BARGE) && f->frametype == AST_FRAME_VOICE) {
+                       /* This hook lets us inject audio into the channel that the spyee is currently
+                        * bridged with. If the spyee isn't bridged with anything yet, nothing will
+                        * be attached and we'll need to continue attempting to attach the barge
+                        * audio hook. */
+                       if (!bridge_connected && attach_barge(spyee_autochan, &spyee_bridge_autochan,
+                                       &csth.bridge_whisper_audiohook, spyer_name, name) == 0) {
+                               bridge_connected = 1;
+                       }
+
+                       if (!bridge_connected) {
+                               continue;
+                       }
+
                        ast_audiohook_lock(&csth.whisper_audiohook);
                        ast_audiohook_lock(&csth.bridge_whisper_audiohook);
                        ast_audiohook_write_frame(&csth.whisper_audiohook, AST_AUDIOHOOK_DIRECTION_WRITE, f);
@@ -717,7 +744,7 @@ static int channel_spy(struct ast_channel *chan, struct ast_autochan *spyee_auto
                        ast_frfree(f);
                        continue;
                }
-               
+
                res = (f->frametype == AST_FRAME_DTMF) ? f->subclass.integer : 0;
                ast_frfree(f);
                if (!res)