Merged revisions 88709 via svnmerge from
[asterisk/asterisk.git] / main / channel.c
index d5fcb0a..d23c2b9 100644 (file)
@@ -3602,11 +3602,6 @@ int ast_do_masquerade(struct ast_channel *original)
        original->tech_pvt = clone->tech_pvt;
        clone->tech_pvt = t_pvt;
 
        original->tech_pvt = clone->tech_pvt;
        clone->tech_pvt = t_pvt;
 
-       /* Swap the readq's */
-       cur = AST_LIST_FIRST(&original->readq);
-       AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq));
-       AST_LIST_HEAD_SET_NOLOCK(&clone->readq, cur);
-
        /* Swap the alertpipes */
        for (i = 0; i < 2; i++) {
                x = original->alertpipe[i];
        /* Swap the alertpipes */
        for (i = 0; i < 2; i++) {
                x = original->alertpipe[i];
@@ -3614,6 +3609,33 @@ int ast_do_masquerade(struct ast_channel *original)
                clone->alertpipe[i] = x;
        }
 
                clone->alertpipe[i] = x;
        }
 
+       /* 
+        * Swap the readq's.  The end result should be this:
+        *
+        *  1) All frames should be on the new (original) channel.
+        *  2) Any frames that were already on the new channel before this
+        *     masquerade need to be at the end of the readq, after all of the
+        *     frames on the old (clone) channel.
+        *  3) The alertpipe needs to get poked for every frame that was already
+        *     on the new channel, since we are now using the alert pipe from the
+        *     old (clone) channel.
+        */
+       {
+               AST_LIST_HEAD_NOLOCK(, ast_frame) tmp_readq;
+               AST_LIST_HEAD_SET_NOLOCK(&tmp_readq, NULL);
+
+               AST_LIST_APPEND_LIST(&tmp_readq, &original->readq, frame_list);
+               AST_LIST_APPEND_LIST(&original->readq, &clone->readq, frame_list);
+
+               while ((cur = AST_LIST_REMOVE_HEAD(&tmp_readq, frame_list))) {
+                       AST_LIST_INSERT_TAIL(&original->readq, cur, frame_list);
+                       if (original->alertpipe[1] > -1) {
+                               int poke = 0;
+                               write(original->alertpipe[1], &poke, sizeof(poke));
+                       }
+               }
+       }
+
        /* Swap the raw formats */
        x = original->rawreadformat;
        original->rawreadformat = clone->rawreadformat;
        /* Swap the raw formats */
        x = original->rawreadformat;
        original->rawreadformat = clone->rawreadformat;
@@ -3622,27 +3644,8 @@ int ast_do_masquerade(struct ast_channel *original)
        original->rawwriteformat = clone->rawwriteformat;
        clone->rawwriteformat = x;
 
        original->rawwriteformat = clone->rawwriteformat;
        clone->rawwriteformat = x;
 
-       /* Save any pending frames on both sides.  Start by counting
-        * how many we're going to need... */
-       x = 0;
-       if (original->alertpipe[1] > -1) {
-               AST_LIST_TRAVERSE(&clone->readq, cur, frame_list)
-                       x++;
-       }
-
-       /* If we had any, prepend them to the ones already in the queue, and 
-        * load up the alertpipe */
-       if (AST_LIST_FIRST(&clone->readq)) {
-               AST_LIST_INSERT_TAIL(&clone->readq, AST_LIST_FIRST(&original->readq), frame_list);
-               AST_LIST_HEAD_SET_NOLOCK(&original->readq, AST_LIST_FIRST(&clone->readq));
-               AST_LIST_HEAD_SET_NOLOCK(&clone->readq, NULL);
-               for (i = 0; i < x; i++)
-                       write(original->alertpipe[1], &x, sizeof(x));
-       }
-       
        clone->_softhangup = AST_SOFTHANGUP_DEV;
 
        clone->_softhangup = AST_SOFTHANGUP_DEV;
 
-
        /* And of course, so does our current state.  Note we need not
           call ast_setstate since the event manager doesn't really consider
           these separate.  We do this early so that the clone has the proper
        /* And of course, so does our current state.  Note we need not
           call ast_setstate since the event manager doesn't really consider
           these separate.  We do this early so that the clone has the proper