/*! \brief Publish single channel user event (for app_userevent compatibility) */ void ast_multi_object_blob_single_channel_publish(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob) { RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, channel_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_multi_object_blob *, multi, NULL, ao2_cleanup); if (!type) { return; } multi = ast_multi_object_blob_create(blob); if (!multi) { return; } channel_snapshot = ast_channel_snapshot_create(chan); ao2_ref(channel_snapshot, +1); ast_multi_object_blob_add(multi, STASIS_UMOS_CHANNEL, channel_snapshot); message = stasis_message_create(type, multi); if (message) { /* app_userevent still publishes to channel */ stasis_publish(ast_channel_topic(chan), message); } }
struct stasis_message *ast_channel_blob_create(struct ast_channel *chan, struct stasis_message_type *type, struct ast_json *blob) { RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); if (chan) { snapshot = ast_channel_snapshot_create(chan); } return create_channel_blob_message(snapshot, type, blob); }
static struct ast_parked_call_payload *parked_call_payload_from_failure(struct ast_channel *chan) { RAII_VAR(struct ast_parked_call_payload *, payload, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup); parkee_snapshot = ast_channel_snapshot_create(chan); if (!parkee_snapshot) { return NULL; } return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0); }
static struct ast_parked_call_payload *parked_call_payload_from_parked_user(struct parked_user *pu, enum ast_parked_call_event_type event_type) { RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup); long int timeout; long int duration; struct timeval now = ast_tvnow(); const char *lot_name = pu->lot->name; ast_channel_lock(pu->chan); parkee_snapshot = ast_channel_snapshot_create(pu->chan); ast_channel_unlock(pu->chan); if (!parkee_snapshot) { return NULL; } timeout = pu->start.tv_sec + (long) pu->time_limit - now.tv_sec; duration = now.tv_sec - pu->start.tv_sec; return ast_parked_call_payload_create(event_type, parkee_snapshot, pu->parker_dial_string, pu->retriever, lot_name, pu->parking_space, timeout, duration); }
void ast_channel_publish_snapshot(struct ast_channel *chan) { RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_SNAPSHOT_STAGE)) { return; } snapshot = ast_channel_snapshot_create(chan); if (!snapshot) { return; } message = stasis_message_create(ast_channel_snapshot_type(), snapshot); if (!message) { return; } ast_assert(ast_channel_topic(chan) != NULL); stasis_publish(ast_channel_topic(chan), message); }
void ast_publish_channel_state(struct ast_channel *chan) { RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup); ast_assert(chan != NULL); if (!chan) { return; } snapshot = ast_channel_snapshot_create(chan); if (!snapshot) { return; } message = stasis_message_create(ast_channel_snapshot_type(), snapshot); if (!message) { return; } ast_assert(ast_channel_topic(chan) != NULL); stasis_publish(ast_channel_topic(chan), message); }
void ast_channel_publish_dial_forward(struct ast_channel *caller, struct ast_channel *peer, struct ast_channel *forwarded, const char *dialstring, const char *dialstatus, const char *forward) { RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup); RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup); RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, peer_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, forwarded_snapshot, NULL, ao2_cleanup); ast_assert(peer != NULL); blob = ast_json_pack("{s: s, s: s, s: s}", "dialstatus", S_OR(dialstatus, ""), "forward", S_OR(forward, ""), "dialstring", S_OR(dialstring, "")); if (!blob) { return; } payload = ast_multi_channel_blob_create(blob); if (!payload) { return; } if (caller) { ast_channel_lock(caller); caller_snapshot = ast_channel_snapshot_create(caller); ast_channel_unlock(caller); if (!caller_snapshot) { return; } ast_multi_channel_blob_add_channel(payload, "caller", caller_snapshot); } ast_channel_lock(peer); peer_snapshot = ast_channel_snapshot_create(peer); ast_channel_unlock(peer); if (!peer_snapshot) { return; } ast_multi_channel_blob_add_channel(payload, "peer", peer_snapshot); if (forwarded) { ast_channel_lock(forwarded); forwarded_snapshot = ast_channel_snapshot_create(forwarded); ast_channel_unlock(forwarded); if (!forwarded_snapshot) { return; } ast_multi_channel_blob_add_channel(payload, "forwarded", forwarded_snapshot); } msg = stasis_message_create(ast_channel_dial_type(), payload); if (!msg) { return; } if (forwarded) { struct stasis_subscription *subscription = stasis_subscribe(ast_channel_topic(peer), dummy_event_cb, NULL); stasis_publish(ast_channel_topic(peer), msg); stasis_unsubscribe_and_join(subscription); } else { publish_message_for_channel_topics(msg, caller); } }
int ast_do_pickup(struct ast_channel *chan, struct ast_channel *target) { struct ast_party_connected_line connected_caller; struct ast_datastore *ds_pickup; const char *chan_name;/*!< A masquerade changes channel names. */ const char *target_name;/*!< A masquerade changes channel names. */ int res = -1; RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup); RAII_VAR(struct ast_channel_snapshot *, target_snapshot, NULL, ao2_cleanup); target_name = ast_strdupa(ast_channel_name(target)); ast_debug(1, "Call pickup on '%s' by '%s'\n", target_name, ast_channel_name(chan)); /* Mark the target to block any call pickup race. */ ds_pickup = ast_datastore_alloc(&pickup_active, NULL); if (!ds_pickup) { ast_log(LOG_WARNING, "Unable to create channel datastore on '%s' for call pickup\n", target_name); return -1; } ast_channel_datastore_add(target, ds_pickup); ast_party_connected_line_init(&connected_caller); ast_party_connected_line_copy(&connected_caller, ast_channel_connected(target)); ast_channel_unlock(target);/* The pickup race is avoided so we do not need the lock anymore. */ /* Reset any earlier private connected id representation */ ast_party_id_reset(&connected_caller.priv); connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; if (ast_channel_connected_line_sub(NULL, chan, &connected_caller, 0) && ast_channel_connected_line_macro(NULL, chan, &connected_caller, 0, 0)) { ast_channel_update_connected_line(chan, &connected_caller, NULL); } ast_party_connected_line_free(&connected_caller); ast_channel_lock(chan); chan_name = ast_strdupa(ast_channel_name(chan)); ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(chan)); ast_channel_unlock(chan); connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; if (ast_answer(chan)) { ast_log(LOG_WARNING, "Unable to answer '%s'\n", chan_name); goto pickup_failed; } if (ast_queue_control(chan, AST_CONTROL_ANSWER)) { ast_log(LOG_WARNING, "Unable to queue answer on '%s'\n", chan_name); goto pickup_failed; } ast_channel_queue_connected_line_update(chan, &connected_caller, NULL); /* setting the HANGUPCAUSE so the ringing channel knows this call was not a missed call */ ast_channel_hangupcause_set(chan, AST_CAUSE_ANSWERED_ELSEWHERE); ast_channel_lock(chan); chan_snapshot = ast_channel_snapshot_create(chan); ast_channel_unlock(chan); if (!chan_snapshot) { goto pickup_failed; } target_snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(target)); if (!target_snapshot) { goto pickup_failed; } if (ast_channel_move(target, chan)) { ast_log(LOG_WARNING, "Unable to complete call pickup of '%s' with '%s'\n", chan_name, target_name); goto pickup_failed; } /* target points to the channel that did the pickup at this point, so use that channel's topic instead of chan */ send_call_pickup_stasis_message(target, chan_snapshot, target_snapshot); res = 0; pickup_failed: ast_channel_lock(target); if (!ast_channel_datastore_remove(target, ds_pickup)) { ast_datastore_free(ds_pickup); } ast_party_connected_line_free(&connected_caller); return res; }