void ast_channel_callid_set(struct ast_channel *chan, struct ast_callid *callid) { char call_identifier_from[AST_CALLID_BUFFER_LENGTH]; char call_identifier_to[AST_CALLID_BUFFER_LENGTH]; call_identifier_from[0] = '\0'; ast_callid_strnprint(call_identifier_to, sizeof(call_identifier_to), callid); if (chan->callid) { ast_callid_strnprint(call_identifier_from, sizeof(call_identifier_from), chan->callid); ast_debug(3, "Channel Call ID changing from %s to %s\n", call_identifier_from, call_identifier_to); /* unbind if already set */ ast_callid_unref(chan->callid); } chan->callid = ast_callid_ref(callid); ast_test_suite_event_notify("CallIDChange", "State: CallIDChange\r\n" "Channel: %s\r\n" "CallID: %s\r\n" "PriorCallID: %s", ast_channel_name(chan), call_identifier_to, call_identifier_from); ast_channel_publish_snapshot(chan); }
struct ast_callid *ast_channel_callid(const struct ast_channel *chan) { if (chan->callid) { ast_callid_ref(chan->callid); return chan->callid; } return NULL; }
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; }