summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/channel.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/main/channel.c b/main/channel.c
index d5fcb0a2d..d23c2b93d 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -3602,11 +3602,6 @@ int ast_do_masquerade(struct ast_channel *original)
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];
@@ -3614,6 +3609,33 @@ int ast_do_masquerade(struct ast_channel *original)
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;
@@ -3622,27 +3644,8 @@ int ast_do_masquerade(struct ast_channel *original)
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;
-
/* 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