int stasis_app_control_bridge_features_init( struct stasis_app_control *control) { struct ast_bridge_features *features; features = ast_bridge_features_new(); if (!features) { return 1; } control->bridge_features = features; return 0; }
int sccpconf_announce_channel_push(struct ast_channel *ast, struct ast_bridge *bridge) { struct ast_bridge_features *features; struct ast_channel *chan; struct announce_pvt *p = NULL; { ast_channel_lock(ast); p = ast_channel_tech_pvt(ast); if (!p) { ast_channel_unlock(ast); return -1; } ao2_ref(p, +1); chan = p->base.chan; if (!chan) { ast_channel_unlock(ast); ao2_cleanup(p); return -1; } ast_channel_ref(chan); ast_channel_unlock(ast); } features = ast_bridge_features_new(); if (!features) { ast_channel_unref(chan); ao2_cleanup(p); return -1; } ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE); // Impart the output channel into the bridge if (ast_bridge_impart(bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) { ast_bridge_features_destroy(features); ast_channel_unref(chan); ao2_cleanup(p); return -1; } ao2_lock(p); ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD); ao2_unlock(p); ao2_cleanup(p); return 0; }
int conf_announce_channel_push(struct ast_channel *ast) { struct ast_bridge_features *features; struct ast_channel *chan; RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup); { SCOPED_CHANNELLOCK(lock, ast); p = ast_channel_tech_pvt(ast); if (!p) { return -1; } ao2_ref(p, +1); chan = p->base.chan; if (!chan) { return -1; } } features = ast_bridge_features_new(); if (!features) { return -1; } ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE); /* Impart the output channel into the bridge */ if (ast_bridge_impart(p->bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { return -1; } ao2_lock(p); ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD); ao2_unlock(p); return 0; }
int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags) { int res; struct ast_bridge *bridge; struct ast_bridge_features chan_features; struct ast_bridge_features *peer_features; /* Setup features. */ res = ast_bridge_features_init(&chan_features); peer_features = ast_bridge_features_new(); if (res || !peer_features) { ast_bridge_features_destroy(peer_features); ast_bridge_features_cleanup(&chan_features); bridge_failed_peer_goto(chan, peer); return -1; } if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features)) { ast_bridge_features_destroy(peer_features); ast_bridge_features_cleanup(&chan_features); bridge_failed_peer_goto(chan, peer); return -1; } /* Create bridge */ bridge = ast_bridge_basic_new(); if (!bridge) { ast_bridge_features_destroy(peer_features); ast_bridge_features_cleanup(&chan_features); bridge_failed_peer_goto(chan, peer); return -1; } ast_bridge_basic_set_flags(bridge, flags); /* Put peer into the bridge */ if (ast_bridge_impart(bridge, peer, NULL, peer_features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT | AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP)) { ast_bridge_destroy(bridge, 0); ast_bridge_features_cleanup(&chan_features); bridge_failed_peer_goto(chan, peer); return -1; } /* Join bridge */ ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, AST_BRIDGE_JOIN_PASS_REFERENCE | AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP); /* * If the bridge was broken for a hangup that isn't real, then * don't run the h extension, because the channel isn't really * hung up. This should really only happen with * AST_SOFTHANGUP_ASYNCGOTO. */ res = -1; ast_channel_lock(chan); if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) { res = 0; } ast_channel_unlock(chan); ast_bridge_features_cleanup(&chan_features); if (res && config->end_bridge_callback) { config->end_bridge_callback(config->end_bridge_callback_data); } return res; }
int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags) { struct ast_bridge_features *features; struct ast_channel *chan; struct ast_channel *owner; RAII_VAR(struct ast_unreal_pvt *, p, NULL, ao2_cleanup); RAII_VAR(struct ast_callid *, bridge_callid, NULL, ast_callid_cleanup); ast_bridge_lock(bridge); bridge_callid = bridge->callid ? ast_callid_ref(bridge->callid) : NULL; ast_bridge_unlock(bridge); { SCOPED_CHANNELLOCK(lock, ast); p = ast_channel_tech_pvt(ast); if (!p) { return -1; } ao2_ref(p, +1); } { SCOPED_AO2LOCK(lock, p); chan = p->chan; if (!chan) { return -1; } owner = p->owner; if (!owner) { return -1; } ast_channel_ref(chan); ast_channel_ref(owner); } if (bridge_callid) { struct ast_callid *chan_callid; struct ast_callid *owner_callid; /* chan side call ID setting */ ast_channel_lock(chan); chan_callid = ast_channel_callid(chan); if (!chan_callid) { ast_channel_callid_set(chan, bridge_callid); } ast_channel_unlock(chan); ast_callid_cleanup(chan_callid); /* owner side call ID setting */ ast_channel_lock(owner); owner_callid = ast_channel_callid(owner); if (!owner_callid) { ast_channel_callid_set(owner, bridge_callid); } ast_channel_unlock(owner); ast_callid_cleanup(owner_callid); } /* We are done with the owner now that its call ID matches the bridge */ ast_channel_unref(owner); owner = NULL; features = ast_bridge_features_new(); if (!features) { ast_channel_unref(chan); return -1; } ast_set_flag(&features->feature_flags, flags); /* Impart the semi2 channel into the bridge */ if (ast_bridge_impart(bridge, chan, NULL, features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_bridge_features_destroy(features); ast_channel_unref(chan); return -1; } ao2_lock(p); ast_set_flag(p, AST_UNREAL_CARETAKER_THREAD); ao2_unlock(p); ast_channel_unref(chan); return 0; }