int *nounlock, struct sip_pvt *replaces_pvt, struct ast_channel *replaces_chan)
{
struct ast_channel *c;
- RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
+ struct ast_bridge *bridge;
if (req->ignore) {
return 0;
}
append_history(p, "Xfer", "INVITE/Replace received");
+ /* Get a ref to ensure the channel cannot go away on us. */
c = ast_channel_ref(p->owner);
/* Fake call progress */
ast_channel_unlock(replaces_chan);
if (bridge) {
+ /*
+ * We have two refs of the channel. One is held in c and the other
+ * is notionally represented by p->owner. The impart is "stealing"
+ * the p->owner ref on success so the bridging system can have
+ * control of when the channel is hung up.
+ */
if (ast_bridge_impart(bridge, c, replaces_chan, NULL,
AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
ast_hangup(c);
- ast_channel_unref(c);
}
+ ao2_ref(bridge, -1);
} else {
ast_channel_move(replaces_chan, c);
ast_hangup(c);
- ast_channel_unref(c);
}
+ ast_channel_unref(c);
sip_pvt_lock(p);
return 0;
}