]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
Merged revisions 375965 via svnmerge from
authorAutomerge script <automerge@asterisk.org>
Tue, 6 Nov 2012 19:28:10 +0000 (19:28 +0000)
committerAutomerge script <automerge@asterisk.org>
Tue, 6 Nov 2012 19:28:10 +0000 (19:28 +0000)
file:///srv/subversion/repos/asterisk/branches/10

................
  r375965 | rmudgett | 2012-11-06 12:27:19 -0600 (Tue, 06 Nov 2012) | 21 lines

  Fix stuck DTMF when bridge is broken.

  When a bridge is broken by an AMI Redirect action or the ChannelRedirect
  application, an in progress DTMF digit could be stuck sending forever.

  * Made simulate a DTMF end event when a bridge is broken and a DTMF digit
  was in progress.

  (closes issue ASTERISK-20492)
  Reported by: Jeremiah Gowdy
  Patches:
        bridge_end_dtmf-v3.patch.txt (license #6358) patch uploaded by Jeremiah Gowdy
        Modified to jira_asterisk_20492_v1.8.patch
        jira_asterisk_20492_v1.8.patch (license #5621) patch uploaded by rmudgett
  Tested by: rmudgett

  Review: https://reviewboard.asterisk.org/r/2169/
  ........

  Merged revisions 375964 from http://svn.asterisk.org/svn/asterisk/branches/1.8
................

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/10-digiumphones@375992 65c4cc65-6c06-0410-ace0-fbb531ad65f3

.cleancount
include/asterisk/channel.h
include/asterisk/features.h
main/channel.c
main/features.c

index c7f5afc52abb7e7f5a8c590e5d36b9b1bf2a1381..425151f3a411f5e088d7753e7c8d016303b1b9d1 100644 (file)
@@ -1,3 +1 @@
-39
-
-
+40
index 8966f541b187acc49321e7c4e40941c4dd40c04a..bbd439389c1978946be9756d09a4ccd13f616682 100644 (file)
@@ -874,6 +874,8 @@ struct ast_channel {
        char macrocontext[AST_MAX_CONTEXT];             /*!< Macro: Current non-macro context. See app_macro.c */
        char macroexten[AST_MAX_EXTENSION];             /*!< Macro: Current non-macro extension. See app_macro.c */
        char emulate_dtmf_digit;                        /*!< Digit being emulated */
+       char sending_dtmf_digit;                        /*!< Digit this channel is currently sending out. (zero if not sending) */
+       struct timeval sending_dtmf_tv;         /*!< The time this channel started sending the current digit. (Invalid if sending_dtmf_digit is zero.) */
 };
 
 /*! \brief ast_channel_tech Properties */
index 42dc57fba2399bd3d10a3f18540d60419a5727ad..1246a5d9a0cf65d4968b3e9d215c4261b63d86a7 100644 (file)
@@ -169,6 +169,18 @@ int ast_parking_ext_valid(const char *exten_str, struct ast_channel *chan, const
 /*! \brief Determine system call pickup extension */
 const char *ast_pickup_ext(void);
 
+/*!
+ * \brief Simulate a DTMF end on a broken bridge channel.
+ *
+ * \param chan Channel sending DTMF that has not ended.
+ * \param digit DTMF digit to stop.
+ * \param start DTMF digit start time.
+ * \param why Reason bridge broken.
+ *
+ * \return Nothing
+ */
+void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why);
+
 /*! \brief Bridge a call, optionally allowing redirection */
 int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config);
 
index 4af26fa0940497bdb4faf23a7501974b8673be93..53ba354c1d8a2217a9f2ea5fbfd38fec55997261 100644 (file)
@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/stringfields.h"
 #include "asterisk/global_datastores.h"
 #include "asterisk/data.h"
+#include "asterisk/features.h"
 
 #ifdef HAVE_EPOLL
 #include <sys/epoll.h>
@@ -4742,6 +4743,11 @@ int ast_senddigit_begin(struct ast_channel *chan, char digit)
        if (!chan->tech->send_digit_begin)
                return 0;
 
+       ast_channel_lock(chan);
+       chan->sending_dtmf_digit = digit;
+       chan->sending_dtmf_tv = ast_tvnow();
+       ast_channel_unlock(chan);
+
        if (!chan->tech->send_digit_begin(chan, digit))
                return 0;
 
@@ -4765,6 +4771,12 @@ int ast_senddigit_end(struct ast_channel *chan, char digit, unsigned int duratio
 {
        int res = -1;
 
+       ast_channel_lock(chan);
+       if (chan->sending_dtmf_digit == digit) {
+               chan->sending_dtmf_digit = 0;
+       }
+       ast_channel_unlock(chan);
+
        if (chan->tech->send_digit_end)
                res = chan->tech->send_digit_end(chan, digit, duration);
 
@@ -6713,6 +6725,8 @@ int ast_do_masquerade(struct ast_channel *original)
        char orig[AST_CHANNEL_NAME];
        char masqn[AST_CHANNEL_NAME];
        char zombn[AST_CHANNEL_NAME];
+       char clone_sending_dtmf_digit;
+       struct timeval clone_sending_dtmf_tv;
 
        /* XXX This operation is a bit odd.  We're essentially putting the guts of
         * the clone channel into the original channel.  Start by killing off the
@@ -6822,6 +6836,10 @@ int ast_do_masquerade(struct ast_channel *original)
        free_translation(clonechan);
        free_translation(original);
 
+       /* Save the current DTMF digit being sent if any. */
+       clone_sending_dtmf_digit = clonechan->sending_dtmf_digit;
+       clone_sending_dtmf_tv = clonechan->sending_dtmf_tv;
+
        /* Save the original name */
        ast_copy_string(orig, original->name, sizeof(orig));
        /* Save the new name */
@@ -7066,6 +7084,15 @@ int ast_do_masquerade(struct ast_channel *original)
 
        ast_channel_unlock(clonechan);
 
+       if (clone_sending_dtmf_digit) {
+               /*
+                * The clonechan was sending a DTMF digit that was not completed
+                * before the masquerade.
+                */
+               ast_bridge_end_dtmf(original, clone_sending_dtmf_digit, clone_sending_dtmf_tv,
+                       "masquerade");
+       }
+
        /*
         * If an indication is currently playing, maintain it on the
         * channel that is taking the place of original.
index 8e0df929b81963dce16854fced575c2359452dec..5520135de30eb6cafcde8581cb201826a908e1c9 100644 (file)
@@ -3922,6 +3922,24 @@ static void clear_dialed_interfaces(struct ast_channel *chan)
        ast_channel_unlock(chan);
 }
 
+void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why)
+{
+       int dead;
+       long duration;
+
+       ast_channel_lock(chan);
+       dead = ast_test_flag(chan, AST_FLAG_ZOMBIE) || ast_check_hangup(chan);
+       ast_channel_unlock(chan);
+       if (dead) {
+               return;
+       }
+
+       duration = ast_tvdiff_ms(ast_tvnow(), start);
+       ast_senddigit_end(chan, digit, duration);
+       ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
+               digit, chan->name, why, duration);
+}
+
 /*!
  * \brief bridge the call and set CDR
  *
@@ -4369,6 +4387,15 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct a
        ast_cel_report_event(chan, AST_CEL_BRIDGE_END, NULL, NULL, peer);
 
 before_you_go:
+       if (chan->sending_dtmf_digit) {
+               ast_bridge_end_dtmf(chan, chan->sending_dtmf_digit, chan->sending_dtmf_tv,
+                       "bridge end");
+       }
+       if (peer->sending_dtmf_digit) {
+               ast_bridge_end_dtmf(peer, peer->sending_dtmf_digit, peer->sending_dtmf_tv,
+                       "bridge end");
+       }
+
        /* Just in case something weird happened and we didn't clean up the silence generator... */
        if (silgen) {
                ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen);