Merged revisions 81599 via svnmerge from
authorRussell Bryant <russell@russellbryant.com>
Wed, 5 Sep 2007 20:58:19 +0000 (20:58 +0000)
committerRussell Bryant <russell@russellbryant.com>
Wed, 5 Sep 2007 20:58:19 +0000 (20:58 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r81599 | russell | 2007-09-05 15:53:41 -0500 (Wed, 05 Sep 2007) | 11 lines

Fix an issue that can occur when you do an attended transfer to parking.  If
you complete the transfer before the announcement of the parking spot finishes,
then the channel being parked will hear the remainder of the announcement.
These changes make it so that will not happen anymore.

Basically, res_features sets a flag on the channel is playing the announcement
to so that the file streaming core knows that it needs to watch out for a
channel masquerade, and if it occurs, to abort the announcement.

(closes BE-182)

........

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

include/asterisk/channel.h
include/asterisk/file.h
main/file.c
main/say.c
res/res_features.c

index 11fb1df..57b7552 100644 (file)
@@ -546,6 +546,9 @@ enum {
        /*! Flag to show channels that this call is hangup due to the fact that the call
            was indeed anwered, but in another channel */
        AST_FLAG_ANSWERED_ELSEWHERE = (1 << 15),
        /*! Flag to show channels that this call is hangup due to the fact that the call
            was indeed anwered, but in another channel */
        AST_FLAG_ANSWERED_ELSEWHERE = (1 << 15),
+       /*! This flag indicates that on a masquerade, an active stream should not
+        *  be carried over */
+       AST_FLAG_MASQ_NOSTREAM = (1 << 16),
 };
 
 /*! \brief ast_bridge_config flags */
 };
 
 /*! \brief ast_bridge_config flags */
index 22a887c..f94fa71 100644 (file)
@@ -133,6 +133,7 @@ struct ast_filestream {
        int lastwriteformat;
        int lasttimeout;
        struct ast_channel *owner;
        int lastwriteformat;
        int lasttimeout;
        struct ast_channel *owner;
+       const char *orig_chan_name;
        FILE *f;
        struct ast_frame fr;    /*!< frame produced by read, typically */
        char *buf;              /*!< buffer pointed to by ast_frame; */
        FILE *f;
        struct ast_frame fr;    /*!< frame produced by read, typically */
        char *buf;              /*!< buffer pointed to by ast_frame; */
index dda1b3d..d64e9cd 100644 (file)
@@ -603,39 +603,68 @@ struct ast_frame *ast_readframe(struct ast_filestream *s)
        return f;
 }
 
        return f;
 }
 
-static int ast_readaudio_callback(void *data)
+enum fsread_res {
+       FSREAD_FAILURE,
+       FSREAD_SUCCESS_SCHED,
+       FSREAD_SUCCESS_NOSCHED,
+};
+
+static int ast_fsread_audio(void *data);
+
+static enum fsread_res ast_readaudio_callback(struct ast_filestream *s)
 {
 {
-       struct ast_filestream *s = data;
        int whennext = 0;
 
        while (!whennext) {
        int whennext = 0;
 
        while (!whennext) {
-               struct ast_frame *fr = s->fmt->read(s, &whennext);
+               struct ast_frame *fr;
+               
+               if (s->orig_chan_name && strcasecmp(s->owner->name, s->orig_chan_name))
+                       goto return_failure;
+               
+               fr = s->fmt->read(s, &whennext);
                if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) {
                        if (fr)
                                ast_log(LOG_WARNING, "Failed to write frame\n");
                if (!fr /* stream complete */ || ast_write(s->owner, fr) /* error writing */) {
                        if (fr)
                                ast_log(LOG_WARNING, "Failed to write frame\n");
-                       s->owner->streamid = -1;
-#ifdef HAVE_ZAPTEL
-                       ast_settimeout(s->owner, 0, NULL, NULL);
-#endif                 
-                       return 0;
+                       goto return_failure;
                }
        }
        if (whennext != s->lasttimeout) {
 #ifdef HAVE_ZAPTEL
                if (s->owner->timingfd > -1)
                }
        }
        if (whennext != s->lasttimeout) {
 #ifdef HAVE_ZAPTEL
                if (s->owner->timingfd > -1)
-                       ast_settimeout(s->owner, whennext, ast_readaudio_callback, s);
+                       ast_settimeout(s->owner, whennext, ast_fsread_audio, s);
                else
 #endif         
                else
 #endif         
-                       s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_readaudio_callback, s);
+                       s->owner->streamid = ast_sched_add(s->owner->sched, whennext/8, ast_fsread_audio, s);
                s->lasttimeout = whennext;
                s->lasttimeout = whennext;
-               return 0;
+               return FSREAD_SUCCESS_NOSCHED;
        }
        }
-       return 1;
+       return FSREAD_SUCCESS_SCHED;
+
+return_failure:
+       s->owner->streamid = -1;
+#ifdef HAVE_ZAPTEL
+       ast_settimeout(s->owner, 0, NULL, NULL);
+#endif                 
+       return FSREAD_FAILURE;
 }
 
 }
 
-static int ast_readvideo_callback(void *data)
+static int ast_fsread_audio(void *data)
+{
+       struct ast_filestream *fs = data;
+       enum fsread_res res;
+
+       res = ast_readaudio_callback(fs);
+
+       if (res == FSREAD_SUCCESS_SCHED)
+               return 1;
+       
+       return 0;
+}
+
+static int ast_fsread_video(void *data);
+
+static enum fsread_res ast_readvideo_callback(struct ast_filestream *s)
 {
 {
-       struct ast_filestream *s = data;
        int whennext = 0;
 
        while (!whennext) {
        int whennext = 0;
 
        while (!whennext) {
@@ -644,15 +673,31 @@ static int ast_readvideo_callback(void *data)
                        if (fr)
                                ast_log(LOG_WARNING, "Failed to write frame\n");
                        s->owner->vstreamid = -1;
                        if (fr)
                                ast_log(LOG_WARNING, "Failed to write frame\n");
                        s->owner->vstreamid = -1;
-                       return 0;
+                       return FSREAD_FAILURE;
                }
        }
                }
        }
+
        if (whennext != s->lasttimeout) {
        if (whennext != s->lasttimeout) {
-               s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext/8, ast_readvideo_callback, s);
+               s->owner->vstreamid = ast_sched_add(s->owner->sched, whennext / 8, 
+                       ast_fsread_video, s);
                s->lasttimeout = whennext;
                s->lasttimeout = whennext;
-               return 0;
+               return FSREAD_SUCCESS_NOSCHED;
        }
        }
-       return 1;
+
+       return FSREAD_SUCCESS_SCHED;
+}
+
+static int ast_fsread_video(void *data)
+{
+       struct ast_filestream *fs = data;
+       enum fsread_res res;
+
+       res = ast_readvideo_callback(fs);
+
+       if (res == FSREAD_SUCCESS_SCHED)
+               return 1;
+       
+       return 0;
 }
 
 int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
 }
 
 int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
@@ -663,11 +708,14 @@ int ast_applystream(struct ast_channel *chan, struct ast_filestream *s)
 
 int ast_playstream(struct ast_filestream *s)
 {
 
 int ast_playstream(struct ast_filestream *s)
 {
+       enum fsread_res res;
+
        if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
        if (s->fmt->format < AST_FORMAT_MAX_AUDIO)
-               ast_readaudio_callback(s);
+               res = ast_readaudio_callback(s);
        else
        else
-               ast_readvideo_callback(s);
-       return 0;
+               res = ast_readvideo_callback(s);
+
+       return (res == FSREAD_FAILURE) ? -1 : 0;
 }
 
 int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
 }
 
 int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
@@ -737,6 +785,8 @@ int ast_closestream(struct ast_filestream *f)
        fclose(f->f);
        if (f->vfs)
                ast_closestream(f->vfs);
        fclose(f->f);
        if (f->vfs)
                ast_closestream(f->vfs);
+       if (f->orig_chan_name)
+               free((void *) f->orig_chan_name);
        ast_module_unref(f->fmt->module);
        ast_free(f);
        return 0;
        ast_module_unref(f->fmt->module);
        ast_free(f);
        return 0;
@@ -788,16 +838,19 @@ int ast_streamfile(struct ast_channel *chan, const char *filename, const char *p
                ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format));
        }
        if (fs){
                ast_debug(1, "Ooh, found a video stream, too, format %s\n", ast_getformatname(vfs->fmt->format));
        }
        if (fs){
+               int res;
+               if (ast_test_flag(chan, AST_FLAG_MASQ_NOSTREAM))
+                       fs->orig_chan_name = ast_strdup(chan->name);
                if (ast_applystream(chan, fs))
                        return -1;
                if (vfs && ast_applystream(chan, vfs))
                        return -1;
                if (ast_applystream(chan, fs))
                        return -1;
                if (vfs && ast_applystream(chan, vfs))
                        return -1;
-               ast_playstream(fs);
-               if (vfs)
-                       ast_playstream(vfs);
+               res = ast_playstream(fs);
+               if (!res && vfs)
+                       res = ast_playstream(vfs);
                ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", chan->name, filename, ast_getformatname(chan->writeformat), preflang ? preflang : "default");
 
                ast_verb(3, "<%s> Playing '%s.%s' (language '%s')\n", chan->name, filename, ast_getformatname(chan->writeformat), preflang ? preflang : "default");
 
-               return 0;
+               return res;
        }
        ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno));
        return -1;
        }
        ast_log(LOG_WARNING, "Unable to open %s (format %s): %s\n", filename, ast_getformatname_multiple(fmt, sizeof(fmt), chan->nativeformats), strerror(errno));
        return -1;
@@ -980,6 +1033,9 @@ static int waitstream_core(struct ast_channel *c, const char *breakon,
        const char *forward, const char *rewind, int skip_ms,
        int audiofd, int cmdfd,  const char *context)
 {
        const char *forward, const char *rewind, int skip_ms,
        int audiofd, int cmdfd,  const char *context)
 {
+       const char *orig_chan_name = NULL;
+       int err = 0;
+
        if (!breakon)
                breakon = "";
        if (!forward)
        if (!breakon)
                breakon = "";
        if (!forward)
@@ -989,10 +1045,22 @@ static int waitstream_core(struct ast_channel *c, const char *breakon,
 
        /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */
        ast_set_flag(c, AST_FLAG_END_DTMF_ONLY);
 
        /* Switch the channel to end DTMF frame only. waitstream_core doesn't care about the start of DTMF. */
        ast_set_flag(c, AST_FLAG_END_DTMF_ONLY);
-       
+
+       if (ast_test_flag(c, AST_FLAG_MASQ_NOSTREAM))
+               orig_chan_name = ast_strdupa(c->name);
+
        while (c->stream) {
                int res;
        while (c->stream) {
                int res;
-               int ms = ast_sched_wait(c->sched);
+               int ms;
+
+               if (orig_chan_name && strcasecmp(orig_chan_name, c->name)) {
+                       ast_stopstream(c);
+                       err = 1;
+                       break;
+               }
+
+               ms = ast_sched_wait(c->sched);
+
                if (ms < 0 && !c->timingfunc) {
                        ast_stopstream(c);
                        break;
                if (ms < 0 && !c->timingfunc) {
                        ast_stopstream(c);
                        break;
@@ -1087,7 +1155,7 @@ static int waitstream_core(struct ast_channel *c, const char *breakon,
 
        ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
 
 
        ast_clear_flag(c, AST_FLAG_END_DTMF_ONLY);
 
-       return (c->_softhangup ? -1 : 0);
+       return (err || c->_softhangup) ? -1 : 0;
 }
 
 int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms)
 }
 
 int ast_waitstream_fr(struct ast_channel *c, const char *breakon, const char *forward, const char *rewind, int ms)
index 9ed4817..9f77d34 100644 (file)
@@ -260,9 +260,9 @@ static int say_digit_str_full(struct ast_channel *chan, const char *str, const c
                        res = ast_streamfile(chan, fn, lang);
                        if (!res) {
                                if ((audiofd  > -1) && (ctrlfd > -1))
                        res = ast_streamfile(chan, fn, lang);
                        if (!res) {
                                if ((audiofd  > -1) && (ctrlfd > -1))
-                                        res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
-                                else
-                                        res = ast_waitstream(chan, ints);
+                                       res = ast_waitstream_full(chan, ints, audiofd, ctrlfd);
+                               else
+                                       res = ast_waitstream(chan, ints);
                        }
                        ast_stopstream(chan);
                }
                        }
                        ast_stopstream(chan);
                }
index f8ff924..a9c252b 100644 (file)
@@ -491,8 +491,12 @@ int ast_park_call(struct ast_channel *chan, struct ast_channel *peer, int timeou
        if (!con)       /* Still no context? Bad */
                ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
        /* Tell the peer channel the number of the parking space */
        if (!con)       /* Still no context? Bad */
                ast_log(LOG_ERROR, "Parking context '%s' does not exist and unable to create\n", parking_con);
        /* Tell the peer channel the number of the parking space */
-       if (peer && pu->parkingnum != -1) /* Only say number if it's a number */
+       if (peer && pu->parkingnum != -1) { /* Only say number if it's a number */
+               /* Make sure we don't start saying digits to the channel being parked */
+               ast_set_flag(peer, AST_FLAG_MASQ_NOSTREAM);
                ast_say_digits(peer, pu->parkingnum, "", peer->language);
                ast_say_digits(peer, pu->parkingnum, "", peer->language);
+               ast_clear_flag(peer, AST_FLAG_MASQ_NOSTREAM);
+       }
        if (con) {
                if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free, registrar))
                        notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);
        if (con) {
                if (!ast_add_extension2(con, 1, pu->parkingexten, 1, NULL, NULL, parkedcall, ast_strdup(pu->parkingexten), ast_free, registrar))
                        notify_metermaids(pu->parkingexten, parking_con, AST_DEVICE_INUSE);