diff options
Diffstat (limited to 'main/bridge_channel.c')
-rw-r--r-- | main/bridge_channel.c | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/main/bridge_channel.c b/main/bridge_channel.c index eba5ae40a..0af688ad4 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -639,18 +639,21 @@ void ast_bridge_channel_kick(struct ast_bridge_channel *bridge_channel, int caus static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *frame) { const struct ast_control_t38_parameters *t38_parameters; + int deferred; ast_assert(frame->frametype != AST_FRAME_BRIDGE_ACTION_SYNC); ast_bridge_channel_lock_bridge(bridge_channel); -/* - * XXX need to implement a deferred write queue for when there - * is no peer channel in the bridge (yet or it was kicked). - * - * The tech decides if a frame needs to be pushed back for deferral. - * simple_bridge/native_bridge are likely the only techs that will do this. - */ - bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame); + + deferred = bridge_channel->bridge->technology->write(bridge_channel->bridge, bridge_channel, frame); + if (deferred) { + struct ast_frame *dup; + + dup = ast_frdup(frame); + if (dup) { + AST_LIST_INSERT_HEAD(&bridge_channel->deferred_queue, dup, frame_list); + } + } /* Remember any owed events to the bridge. */ switch (frame->frametype) { @@ -754,6 +757,18 @@ void bridge_channel_settle_owed_events(struct ast_bridge *orig_bridge, struct as } } +void bridge_channel_queue_deferred_frames(struct ast_bridge_channel *bridge_channel) +{ + struct ast_frame *frame; + + ast_channel_lock(bridge_channel->chan); + while ((frame = AST_LIST_REMOVE_HEAD(&bridge_channel->deferred_queue, frame_list))) { + ast_queue_frame_head(bridge_channel->chan, frame); + ast_frfree(frame); + } + ast_channel_unlock(bridge_channel->chan); +} + /*! * \internal * \brief Suspend a channel from a bridge. @@ -2854,6 +2869,11 @@ static void bridge_channel_destroy(void *obj) } ast_alertpipe_close(bridge_channel->alert_pipe); + /* Flush any unhandled deferred_queue frames. */ + while ((fr = AST_LIST_REMOVE_HEAD(&bridge_channel->deferred_queue, frame_list))) { + ast_frfree(fr); + } + ast_cond_destroy(&bridge_channel->cond); ao2_cleanup(bridge_channel->write_format); |