static void ari_bridges_play_new(const char **args_media, size_t args_media_count, const char *args_lang, int args_offset_ms, int args_skipms, const char *args_playback_id, struct ast_ari_response *response, struct ast_bridge *bridge) { RAII_VAR(struct ast_channel *, play_channel, NULL, ast_hangup); RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); RAII_VAR(struct stasis_forward *, channel_forward, NULL, stasis_forward_cancel); RAII_VAR(char *, playback_url, NULL, ast_free); struct stasis_topic *channel_topic; struct stasis_topic *bridge_topic; struct bridge_channel_control_thread_data *thread_data; pthread_t threadid; if (!(play_channel = prepare_bridge_media_channel("Announcer"))) { ast_ari_response_error( response, 500, "Internal Error", "Could not create playback channel"); return; } ast_debug(1, "Created announcer channel '%s'\n", ast_channel_name(play_channel)); bridge_topic = ast_bridge_topic(bridge); channel_topic = ast_channel_topic(play_channel); /* Forward messages from the playback channel topic to the bridge topic so that anything listening for * messages on the bridge topic will receive the playback start/stop messages. Other messages that would * go to this channel will be suppressed since the channel is marked as internal. */ if (!bridge_topic || !channel_topic || !(channel_forward = stasis_forward_all(channel_topic, bridge_topic))) { ast_ari_response_error( response, 500, "Internal Error", "Could not forward playback channel stasis messages to bridge topic"); return; } if (ast_unreal_channel_push_to_bridge(play_channel, bridge, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE | AST_BRIDGE_CHANNEL_FLAG_LONELY)) { ast_ari_response_error( response, 500, "Internal Error", "Failed to put playback channel into the bridge"); return; } control = stasis_app_control_create(play_channel); if (control == NULL) { ast_ari_response_alloc_failed(response); return; } ao2_lock(control); if (ari_bridges_play_helper(args_media, args_media_count, args_lang, args_offset_ms, args_skipms, args_playback_id, response, bridge, control, &json, &playback_url)) { ao2_unlock(control); return; } ao2_unlock(control); if (stasis_app_bridge_playback_channel_add(bridge, play_channel, control)) { ast_ari_response_alloc_failed(response); return; } /* Give play_channel and control reference to the thread data */ thread_data = ast_malloc(sizeof(*thread_data) + strlen(bridge->uniqueid) + 1); if (!thread_data) { stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control); ast_ari_response_alloc_failed(response); return; } thread_data->bridge_channel = play_channel; thread_data->control = control; thread_data->forward = channel_forward; /* Safe */ strcpy(thread_data->bridge_id, bridge->uniqueid); if (ast_pthread_create_detached(&threadid, NULL, bridge_channel_control_thread, thread_data)) { stasis_app_bridge_playback_channel_remove((char *)bridge->uniqueid, control); ast_ari_response_alloc_failed(response); ast_free(thread_data); return; } /* These are owned by the other thread now, so we don't want RAII_VAR disposing of them. */ play_channel = NULL; control = NULL; channel_forward = NULL; ast_ari_response_created(response, playback_url, ast_json_ref(json)); }
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2) { struct timeval eventtime; struct ast_event *ev; const char *peername = ""; struct ast_channel *peer; char *linkedid = ast_strdupa(ast_channel_linkedid(chan)); /* Make sure a reload is not occurring while we're checking to see if this * is an event that we care about. We could lose an important event in this * process otherwise. */ ast_mutex_lock(&reload_lock); /* Record the linkedid of new channels if we are tracking LINKEDID_END even if we aren't * reporting on CHANNEL_START so we can track when to send LINKEDID_END */ if (cel_enabled && ast_cel_track_event(AST_CEL_LINKEDID_END) && event_type == AST_CEL_CHANNEL_START && linkedid) { if (ast_cel_linkedid_ref(linkedid)) { ast_mutex_unlock(&reload_lock); return -1; } } if (!cel_enabled || !ast_cel_track_event(event_type)) { ast_mutex_unlock(&reload_lock); return 0; } if (event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END) { char *app; if (!(app = ao2_find(appset, (char *) ast_channel_appl(chan), OBJ_POINTER))) { ast_mutex_unlock(&reload_lock); return 0; } ao2_ref(app, -1); } ast_mutex_unlock(&reload_lock); ast_channel_lock(chan); peer = ast_bridged_channel(chan); if (peer) { ast_channel_ref(peer); } ast_channel_unlock(chan); if (peer) { ast_channel_lock(peer); peername = ast_strdupa(ast_channel_name(peer)); ast_channel_unlock(peer); } else if (peer2) { ast_channel_lock(peer2); peername = ast_strdupa(ast_channel_name(peer2)); ast_channel_unlock(peer2); } if (!userdefevname) { userdefevname = ""; } if (!extra) { extra = ""; } eventtime = ast_tvnow(); ast_channel_lock(chan); ev = ast_event_new(AST_EVENT_CEL, AST_EVENT_IE_CEL_EVENT_TYPE, AST_EVENT_IE_PLTYPE_UINT, event_type, AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec, AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec, AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, userdefevname, AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""), AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""), AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""), AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""), AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_dialed(chan)->number.str, ""), AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, ast_channel_exten(chan), AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, ast_channel_context(chan), AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, ast_channel_name(chan), AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_appl(chan), ""), AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, S_OR(ast_channel_data(chan), ""), AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, ast_channel_amaflags(chan), AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, ast_channel_accountcode(chan), AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, ast_channel_peeraccount(chan), AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, ast_channel_uniqueid(chan), AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, ast_channel_linkedid(chan), AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, ast_channel_userfield(chan), AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, extra, AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, peername, AST_EVENT_IE_END); ast_channel_unlock(chan); if (peer) { peer = ast_channel_unref(peer); } if (ev && ast_event_queue(ev)) { ast_event_destroy(ev); return -1; } return 0; }
static int handle_incoming_request(struct ast_sip_session *session, struct pjsip_rx_data *rdata) { struct ast_datastore *sip_session_datastore; struct ast_channel *other_party; int has_feature; int has_reason; if (!session->channel) { return 0; } has_feature = has_call_feature(rdata); has_reason = has_diversion_reason(rdata); if (!has_feature && !has_reason) { /* If we don't have a call feature or diversion reason or if it's not a feature this module is related to then there is nothing to do. */ return 0; } /* Check bridge status... */ other_party = ast_channel_bridge_peer(session->channel); if (!other_party) { /* The channel wasn't in a two party bridge */ ast_log(LOG_WARNING, "%s (%s) attempted to transfer to voicemail, " "but was not in a two party bridge.\n", ast_sorcery_object_get_id(session->endpoint), ast_channel_name(session->channel)); send_response(session, 400, rdata); return -1; } sip_session_datastore = ast_sip_session_alloc_datastore( &call_feature_info, DATASTORE_NAME); if (!sip_session_datastore) { ast_channel_unref(other_party); send_response(session, 500, rdata); return -1; } sip_session_datastore->data = other_party; if (ast_sip_session_add_datastore(session, sip_session_datastore)) { ao2_ref(sip_session_datastore, -1); send_response(session, 500, rdata); return -1; } if (has_feature) { pbx_builtin_setvar_helper(other_party, SEND_TO_VM_HEADER, SEND_TO_VM_HEADER_VALUE); } if (has_reason) { pbx_builtin_setvar_helper(other_party, SEND_TO_VM_REDIRECT, SEND_TO_VM_REDIRECT_VALUE); } ao2_ref(sip_session_datastore, -1); return 0; }