|
|
|
@@ -109,15 +109,6 @@ struct ao2_container *app_bridges_moh;
|
|
|
|
|
|
|
|
|
|
struct ao2_container *app_bridges_playback;
|
|
|
|
|
|
|
|
|
|
static struct ast_json *stasis_end_json_payload(struct ast_channel_snapshot *snapshot,
|
|
|
|
|
const struct stasis_message_sanitizer *sanitize)
|
|
|
|
|
{
|
|
|
|
|
return ast_json_pack("{s: s, s: o, s: o}",
|
|
|
|
|
"type", "StasisEnd",
|
|
|
|
|
"timestamp", ast_json_timeval(ast_tvnow(), NULL),
|
|
|
|
|
"channel", ast_channel_snapshot_to_json(snapshot, sanitize));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static struct ast_json *stasis_end_to_json(struct stasis_message *message,
|
|
|
|
|
const struct stasis_message_sanitizer *sanitize)
|
|
|
|
|
{
|
|
|
|
@@ -128,12 +119,59 @@ static struct ast_json *stasis_end_to_json(struct stasis_message *message,
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return stasis_end_json_payload(payload->snapshot, sanitize);
|
|
|
|
|
return ast_json_pack("{s: s, s: o, s: o}",
|
|
|
|
|
"type", "StasisEnd",
|
|
|
|
|
"timestamp", ast_json_timeval(ast_tvnow(), NULL),
|
|
|
|
|
"channel", ast_channel_snapshot_to_json(payload->snapshot, sanitize));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
STASIS_MESSAGE_TYPE_DEFN(ast_stasis_end_message_type,
|
|
|
|
|
STASIS_MESSAGE_TYPE_DEFN(app_end_message_type,
|
|
|
|
|
.to_json = stasis_end_to_json);
|
|
|
|
|
|
|
|
|
|
struct start_message_blob {
|
|
|
|
|
struct ast_channel_snapshot *channel; /*!< Channel that is entering Stasis() */
|
|
|
|
|
struct ast_channel_snapshot *replace_channel; /*!< Channel that is being replaced (optional) */
|
|
|
|
|
struct ast_json *blob; /*!< JSON blob containing timestamp and args */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static struct ast_json *stasis_start_to_json(struct stasis_message *message,
|
|
|
|
|
const struct stasis_message_sanitizer *sanitize)
|
|
|
|
|
{
|
|
|
|
|
struct start_message_blob *payload = stasis_message_data(message);
|
|
|
|
|
struct ast_json *msg;
|
|
|
|
|
|
|
|
|
|
if (sanitize && sanitize->channel_snapshot &&
|
|
|
|
|
sanitize->channel_snapshot(payload->channel)) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msg = ast_json_pack("{s: s, s: O, s: O, s: o}",
|
|
|
|
|
"type", "StasisStart",
|
|
|
|
|
"timestamp", ast_json_object_get(payload->blob, "timestamp"),
|
|
|
|
|
"args", ast_json_object_get(payload->blob, "args"),
|
|
|
|
|
"channel", ast_channel_snapshot_to_json(payload->channel, NULL));
|
|
|
|
|
if (!msg) {
|
|
|
|
|
ast_log(LOG_ERROR, "Failed to pack JSON for StasisStart message\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (payload->replace_channel) {
|
|
|
|
|
int res = ast_json_object_set(msg, "replace_channel",
|
|
|
|
|
ast_channel_snapshot_to_json(payload->replace_channel, NULL));
|
|
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
ast_json_unref(msg);
|
|
|
|
|
ast_log(LOG_ERROR, "Failed to append JSON for StasisStart message\n");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return msg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
STASIS_MESSAGE_TYPE_DEFN_LOCAL(start_message_type,
|
|
|
|
|
.to_json = stasis_start_to_json);
|
|
|
|
|
|
|
|
|
|
const char *stasis_app_name(const struct stasis_app *app)
|
|
|
|
|
{
|
|
|
|
|
return app_name(app);
|
|
|
|
@@ -862,51 +900,64 @@ char *app_get_replace_channel_app(struct ast_channel *chan)
|
|
|
|
|
return replace_channel_app;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int send_start_msg_snapshots(struct stasis_app *app,
|
|
|
|
|
static void start_message_blob_dtor(void *obj)
|
|
|
|
|
{
|
|
|
|
|
struct start_message_blob *payload = obj;
|
|
|
|
|
|
|
|
|
|
ao2_cleanup(payload->channel);
|
|
|
|
|
ao2_cleanup(payload->replace_channel);
|
|
|
|
|
ast_json_unref(payload->blob);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app *app,
|
|
|
|
|
int argc, char *argv[], struct ast_channel_snapshot *snapshot,
|
|
|
|
|
struct ast_channel_snapshot *replace_channel_snapshot)
|
|
|
|
|
{
|
|
|
|
|
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
|
|
|
|
|
RAII_VAR(struct ast_json *, json_blob, NULL, ast_json_unref);
|
|
|
|
|
struct ast_json *json_args;
|
|
|
|
|
struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
|
|
|
|
|
RAII_VAR(struct start_message_blob *, payload, NULL, ao2_cleanup);
|
|
|
|
|
struct stasis_message *msg;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (sanitize && sanitize->channel_snapshot
|
|
|
|
|
&& sanitize->channel_snapshot(snapshot)) {
|
|
|
|
|
return 0;
|
|
|
|
|
payload = ao2_alloc(sizeof(*payload), start_message_blob_dtor);
|
|
|
|
|
if (!payload) {
|
|
|
|
|
ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msg = ast_json_pack("{s: s, s: o, s: [], s: o}",
|
|
|
|
|
"type", "StasisStart",
|
|
|
|
|
payload->channel = ao2_bump(snapshot);
|
|
|
|
|
payload->replace_channel = ao2_bump(replace_channel_snapshot);
|
|
|
|
|
|
|
|
|
|
json_blob = ast_json_pack("{s: o, s: []}",
|
|
|
|
|
"timestamp", ast_json_timeval(ast_tvnow(), NULL),
|
|
|
|
|
"args",
|
|
|
|
|
"channel", ast_channel_snapshot_to_json(snapshot, NULL));
|
|
|
|
|
if (!msg) {
|
|
|
|
|
"args");
|
|
|
|
|
if (!json_blob) {
|
|
|
|
|
ast_log(LOG_ERROR, "Error packing JSON for StasisStart message\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (replace_channel_snapshot) {
|
|
|
|
|
int res = ast_json_object_set(msg, "replace_channel",
|
|
|
|
|
ast_channel_snapshot_to_json(replace_channel_snapshot, NULL));
|
|
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Append arguments to args array */
|
|
|
|
|
json_args = ast_json_object_get(msg, "args");
|
|
|
|
|
json_args = ast_json_object_get(json_blob, "args");
|
|
|
|
|
ast_assert(json_args != NULL);
|
|
|
|
|
for (i = 0; i < argc; ++i) {
|
|
|
|
|
int r = ast_json_array_append(json_args,
|
|
|
|
|
ast_json_string_create(argv[i]));
|
|
|
|
|
if (r != 0) {
|
|
|
|
|
ast_log(LOG_ERROR, "Error appending start message\n");
|
|
|
|
|
ast_log(LOG_ERROR, "Error appending to StasisStart message\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_send(app, msg);
|
|
|
|
|
payload->blob = ast_json_ref(json_blob);
|
|
|
|
|
|
|
|
|
|
msg = stasis_message_create(start_message_type(), payload);
|
|
|
|
|
if (!msg) {
|
|
|
|
|
ast_log(LOG_ERROR, "Error sending StasisStart message\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stasis_publish(ast_channel_topic(chan), msg);
|
|
|
|
|
ao2_ref(msg, -1);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -928,31 +979,36 @@ static int send_start_msg(struct stasis_app *app, struct ast_channel *chan,
|
|
|
|
|
if (!snapshot) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
return send_start_msg_snapshots(app, argc, argv, snapshot, replace_channel_snapshot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int send_end_msg_snapshot(struct stasis_app *app, struct ast_channel_snapshot *snapshot)
|
|
|
|
|
{
|
|
|
|
|
struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
|
|
|
|
|
struct ast_json *msg;
|
|
|
|
|
|
|
|
|
|
if (sanitize && sanitize->channel_snapshot
|
|
|
|
|
&& sanitize->channel_snapshot(snapshot)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
msg = stasis_end_json_payload(snapshot, sanitize);
|
|
|
|
|
if (!msg) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
app_send(app, msg);
|
|
|
|
|
ast_json_unref(msg);
|
|
|
|
|
return 0;
|
|
|
|
|
return send_start_msg_snapshots(chan, app, argc, argv, snapshot, replace_channel_snapshot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void remove_masquerade_store(struct ast_channel *chan);
|
|
|
|
|
|
|
|
|
|
int app_send_end_msg(struct stasis_app *app, struct ast_channel *chan)
|
|
|
|
|
{
|
|
|
|
|
struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
|
|
|
|
|
struct ast_json *blob;
|
|
|
|
|
|
|
|
|
|
if (sanitize && sanitize->channel
|
|
|
|
|
&& sanitize->channel(chan)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
blob = ast_json_pack("{s: s}", "app", app_name(app));
|
|
|
|
|
if (!blob) {
|
|
|
|
|
ast_log(LOG_ERROR, "Error packing JSON for StasisEnd message\n");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stasis_app_channel_set_stasis_end_published(chan);
|
|
|
|
|
remove_masquerade_store(chan);
|
|
|
|
|
ast_channel_publish_blob(chan, app_end_message_type(), blob);
|
|
|
|
|
|
|
|
|
|
ast_json_unref(blob);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int masq_match_cb(void *obj, void *data, int flags)
|
|
|
|
|
{
|
|
|
|
|
struct stasis_app_control *control = obj;
|
|
|
|
@@ -968,32 +1024,22 @@ static int masq_match_cb(void *obj, void *data, int flags)
|
|
|
|
|
|
|
|
|
|
static void channel_stolen_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
|
|
|
|
|
{
|
|
|
|
|
struct ast_channel_snapshot *snapshot;
|
|
|
|
|
struct stasis_app_control *control;
|
|
|
|
|
|
|
|
|
|
/* grab a snapshot */
|
|
|
|
|
snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(new_chan));
|
|
|
|
|
if (!snapshot) {
|
|
|
|
|
ast_log(LOG_ERROR, "Could not get snapshot for masqueraded channel\n");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* find control */
|
|
|
|
|
control = ao2_callback(app_controls, 0, masq_match_cb, old_chan);
|
|
|
|
|
if (!control) {
|
|
|
|
|
ast_log(LOG_ERROR, "Could not find control for masqueraded channel\n");
|
|
|
|
|
ao2_cleanup(snapshot);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* send the StasisEnd message to the app */
|
|
|
|
|
send_end_msg_snapshot(control_app(control), snapshot);
|
|
|
|
|
app_send_end_msg(control_app(control), new_chan);
|
|
|
|
|
|
|
|
|
|
/* remove the datastore */
|
|
|
|
|
remove_masquerade_store(old_chan);
|
|
|
|
|
|
|
|
|
|
ao2_cleanup(control);
|
|
|
|
|
ao2_cleanup(snapshot);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void channel_replaced_cb(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
|
|
|
|
@@ -1032,10 +1078,10 @@ static void channel_replaced_cb(void *data, struct ast_channel *old_chan, struct
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* send the StasisStart with replace_channel to the app */
|
|
|
|
|
send_start_msg_snapshots(control_app(control), 0, NULL, new_snapshot,
|
|
|
|
|
send_start_msg_snapshots(new_chan, control_app(control), 0, NULL, new_snapshot,
|
|
|
|
|
old_snapshot);
|
|
|
|
|
/* send the StasisEnd message to the app */
|
|
|
|
|
send_end_msg_snapshot(control_app(control), old_snapshot);
|
|
|
|
|
app_send_end_msg(control_app(control), old_chan);
|
|
|
|
|
|
|
|
|
|
/* fixup channel topic forwards */
|
|
|
|
|
if (app_replace_channel_forwards(control_app(control), old_snapshot->uniqueid, new_chan)) {
|
|
|
|
@@ -1090,33 +1136,6 @@ static void remove_masquerade_store(struct ast_channel *chan)
|
|
|
|
|
ast_datastore_free(datastore);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int send_end_msg(struct stasis_app *app, struct ast_channel *chan)
|
|
|
|
|
{
|
|
|
|
|
struct ast_channel_snapshot *snapshot;
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
|
|
ast_assert(chan != NULL);
|
|
|
|
|
|
|
|
|
|
/* A masquerade has occurred and this message will be wrong so it
|
|
|
|
|
* has already been sent elsewhere. */
|
|
|
|
|
if (!has_masquerade_store(chan)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set channel info */
|
|
|
|
|
snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
|
|
|
|
|
if (!snapshot) {
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (send_end_msg_snapshot(app, snapshot)) {
|
|
|
|
|
res = -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ao2_cleanup(snapshot);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void stasis_app_control_execute_until_exhausted(struct ast_channel *chan, struct stasis_app_control *control)
|
|
|
|
|
{
|
|
|
|
|
while (!control_is_done(control)) {
|
|
|
|
@@ -1232,14 +1251,6 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = send_start_msg(app, chan, argc, argv);
|
|
|
|
|
if (res != 0) {
|
|
|
|
|
ast_log(LOG_ERROR,
|
|
|
|
|
"Error sending start message to '%s'\n", app_name);
|
|
|
|
|
remove_masquerade_store(chan);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = app_subscribe_channel(app, chan);
|
|
|
|
|
if (res != 0) {
|
|
|
|
|
ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
|
|
|
|
@@ -1248,6 +1259,14 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
res = send_start_msg(app, chan, argc, argv);
|
|
|
|
|
if (res != 0) {
|
|
|
|
|
ast_log(LOG_ERROR,
|
|
|
|
|
"Error sending start message to '%s'\n", app_name);
|
|
|
|
|
remove_masquerade_store(chan);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Pull queued prestart commands and execute */
|
|
|
|
|
control_prestart_dispatch_all(control, chan);
|
|
|
|
|
|
|
|
|
@@ -1327,9 +1346,9 @@ int stasis_app_exec(struct ast_channel *chan, const char *app_name, int argc,
|
|
|
|
|
|
|
|
|
|
/* Only publish a stasis_end event if it hasn't already been published */
|
|
|
|
|
if (!stasis_app_channel_is_stasis_end_published(chan)) {
|
|
|
|
|
app_unsubscribe_channel(app, chan);
|
|
|
|
|
res = send_end_msg(app, chan);
|
|
|
|
|
remove_masquerade_store(chan);
|
|
|
|
|
/* A masquerade has occurred and this message will be wrong so it
|
|
|
|
|
* has already been sent elsewhere. */
|
|
|
|
|
res = has_masquerade_store(chan) && app_send_end_msg(app, chan);
|
|
|
|
|
if (res != 0) {
|
|
|
|
|
ast_log(LOG_ERROR,
|
|
|
|
|
"Error sending end message to %s\n", app_name);
|
|
|
|
@@ -1853,15 +1872,8 @@ void stasis_app_unref(void)
|
|
|
|
|
ast_module_unref(ast_module_info->self);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Subscription to StasisEnd events
|
|
|
|
|
*/
|
|
|
|
|
struct stasis_subscription *stasis_end_sub;
|
|
|
|
|
|
|
|
|
|
static int unload_module(void)
|
|
|
|
|
{
|
|
|
|
|
stasis_end_sub = stasis_unsubscribe(stasis_end_sub);
|
|
|
|
|
|
|
|
|
|
stasis_app_unregister_event_sources();
|
|
|
|
|
|
|
|
|
|
messaging_cleanup();
|
|
|
|
@@ -1882,7 +1894,8 @@ static int unload_module(void)
|
|
|
|
|
ao2_cleanup(app_bridges_playback);
|
|
|
|
|
app_bridges_playback = NULL;
|
|
|
|
|
|
|
|
|
|
STASIS_MESSAGE_TYPE_CLEANUP(ast_stasis_end_message_type);
|
|
|
|
|
STASIS_MESSAGE_TYPE_CLEANUP(app_end_message_type);
|
|
|
|
|
STASIS_MESSAGE_TYPE_CLEANUP(start_message_type);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@@ -1896,6 +1909,15 @@ static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapsho
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* \brief Sanitization callback for channels */
|
|
|
|
|
static int channel_sanitizer(const struct ast_channel *chan)
|
|
|
|
|
{
|
|
|
|
|
if (!chan || !(ast_channel_tech(chan)->properties & AST_CHAN_TP_INTERNAL)) {
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* \brief Sanitization callback for channel unique IDs */
|
|
|
|
|
static int channel_id_sanitizer(const char *id)
|
|
|
|
|
{
|
|
|
|
@@ -1908,6 +1930,7 @@ static int channel_id_sanitizer(const char *id)
|
|
|
|
|
struct stasis_message_sanitizer app_sanitizer = {
|
|
|
|
|
.channel_id = channel_id_sanitizer,
|
|
|
|
|
.channel_snapshot = channel_snapshot_sanitizer,
|
|
|
|
|
.channel = channel_sanitizer,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct stasis_message_sanitizer *stasis_app_get_sanitizer(void)
|
|
|
|
@@ -1915,21 +1938,7 @@ struct stasis_message_sanitizer *stasis_app_get_sanitizer(void)
|
|
|
|
|
return &app_sanitizer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void remove_masquerade_store_by_name(const char *channel_name)
|
|
|
|
|
{
|
|
|
|
|
struct ast_channel *chan;
|
|
|
|
|
|
|
|
|
|
chan = ast_channel_get_by_name(channel_name);
|
|
|
|
|
if (!chan) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remove_masquerade_store(chan);
|
|
|
|
|
ast_channel_unref(chan);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void check_for_stasis_end(void *data, struct stasis_subscription *sub,
|
|
|
|
|
struct stasis_message *message)
|
|
|
|
|
void app_end_message_handler(struct stasis_message *message)
|
|
|
|
|
{
|
|
|
|
|
struct ast_channel_blob *payload;
|
|
|
|
|
struct ast_channel_snapshot *snapshot;
|
|
|
|
@@ -1938,10 +1947,6 @@ static void check_for_stasis_end(void *data, struct stasis_subscription *sub,
|
|
|
|
|
size_t alloc_size;
|
|
|
|
|
const char *channels[1];
|
|
|
|
|
|
|
|
|
|
if (stasis_message_type(message) != ast_stasis_end_message_type()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
payload = stasis_message_data(message);
|
|
|
|
|
snapshot = payload->snapshot;
|
|
|
|
|
app_name = ast_json_string_get(ast_json_object_get(payload->blob, "app"));
|
|
|
|
@@ -1953,8 +1958,6 @@ static void check_for_stasis_end(void *data, struct stasis_subscription *sub,
|
|
|
|
|
|
|
|
|
|
channels[0] = channel_uri;
|
|
|
|
|
stasis_app_unsubscribe(app_name, channels, ARRAY_LEN(channels), NULL);
|
|
|
|
|
|
|
|
|
|
remove_masquerade_store_by_name(snapshot->name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static const struct ast_datastore_info stasis_internal_channel_info = {
|
|
|
|
@@ -2027,7 +2030,10 @@ int stasis_app_channel_is_internal(struct ast_channel *chan)
|
|
|
|
|
|
|
|
|
|
static int load_module(void)
|
|
|
|
|
{
|
|
|
|
|
if (STASIS_MESSAGE_TYPE_INIT(ast_stasis_end_message_type) != 0) {
|
|
|
|
|
if (STASIS_MESSAGE_TYPE_INIT(start_message_type) != 0) {
|
|
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
|
|
|
|
}
|
|
|
|
|
if (STASIS_MESSAGE_TYPE_INIT(app_end_message_type) != 0) {
|
|
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
|
|
|
|
}
|
|
|
|
|
apps_registry = ao2_container_alloc(APPS_NUM_BUCKETS, app_hash, app_compare);
|
|
|
|
@@ -2053,12 +2059,6 @@ static int load_module(void)
|
|
|
|
|
|
|
|
|
|
stasis_app_register_event_sources();
|
|
|
|
|
|
|
|
|
|
stasis_end_sub = stasis_subscribe(ast_channel_topic_all(), check_for_stasis_end, NULL);
|
|
|
|
|
if (!stasis_end_sub) {
|
|
|
|
|
unload_module();
|
|
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return AST_MODULE_LOAD_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|