diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 51 |
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 |