[asterisk-commits] dlee: branch dlee/ASTERISK-22296 r397834 - in /team/dlee/ASTERISK-22296: ./ c...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Tue Aug 27 14:36:55 CDT 2013
Author: dlee
Date: Tue Aug 27 14:36:52 2013
New Revision: 397834
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=397834
Log:
Merged revisions 397713-397816 from http://svn.asterisk.org/svn/asterisk/branches/12
Modified:
team/dlee/ASTERISK-22296/ (props changed)
team/dlee/ASTERISK-22296/channels/chan_dahdi.c
team/dlee/ASTERISK-22296/channels/chan_iax2.c
team/dlee/ASTERISK-22296/channels/chan_motif.c
team/dlee/ASTERISK-22296/channels/chan_sip.c
team/dlee/ASTERISK-22296/channels/sig_analog.c
team/dlee/ASTERISK-22296/channels/sig_pri.c
team/dlee/ASTERISK-22296/channels/sig_ss7.c
team/dlee/ASTERISK-22296/main/astmm.c
team/dlee/ASTERISK-22296/main/stasis_bridges.c
team/dlee/ASTERISK-22296/res/res_ari_asterisk.c
team/dlee/ASTERISK-22296/res/res_ari_bridges.c
team/dlee/ASTERISK-22296/res/res_ari_events.c
team/dlee/ASTERISK-22296/res/res_stasis.c
team/dlee/ASTERISK-22296/res/stasis/app.c
team/dlee/ASTERISK-22296/res/stasis/app.h
team/dlee/ASTERISK-22296/rest-api-templates/param_parsing.mustache
team/dlee/ASTERISK-22296/rest-api-templates/res_ari_resource.c.mustache
Propchange: team/dlee/ASTERISK-22296/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.
Propchange: team/dlee/ASTERISK-22296/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Aug 27 14:36:52 2013
@@ -1,1 +1,1 @@
-/branches/12:1-397699
+/branches/12:1-397832
Modified: team/dlee/ASTERISK-22296/channels/chan_dahdi.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/chan_dahdi.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/chan_dahdi.c (original)
+++ team/dlee/ASTERISK-22296/channels/chan_dahdi.c Tue Aug 27 14:36:52 2013
@@ -3686,6 +3686,7 @@
snprintf(cause_str, sizeof(cause_str), "R2 DISCONNECT (%s)", openr2_proto_get_disconnect_string(cause));
datalen += strlen(cause_str);
cause_code = ast_alloca(datalen);
+ memset(cause_code, 0, datalen);
cause_code->ast_cause = dahdi_r2_cause_to_ast_cause(cause);
ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
ast_copy_string(cause_code->code, cause_str, datalen + 1 - sizeof(*cause_code));
Modified: team/dlee/ASTERISK-22296/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/chan_iax2.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/chan_iax2.c (original)
+++ team/dlee/ASTERISK-22296/channels/chan_iax2.c Tue Aug 27 14:36:52 2013
@@ -9996,6 +9996,7 @@
data_size += strlen(subclass);
cause_code = ast_alloca(data_size);
+ memset(cause_code, 0, data_size);
ast_copy_string(cause_code->chan_name, ast_channel_name(iaxs[fr->callno]->owner), AST_CHANNEL_NAME);
cause_code->ast_cause = ies.causecode;
Modified: team/dlee/ASTERISK-22296/channels/chan_motif.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/chan_motif.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/chan_motif.c (original)
+++ team/dlee/ASTERISK-22296/channels/chan_motif.c Tue Aug 27 14:36:52 2013
@@ -2532,7 +2532,8 @@
/* Size of the string making up the cause code is "Motif " + text */
data_size += 6 + strlen(iks_name(text));
- cause_code = ast_malloc(data_size);
+ cause_code = ast_alloca(data_size);
+ memset(cause_code, 0, data_size);
/* Get the appropriate cause code mapping for this reason */
for (i = 0; i < ARRAY_LEN(jingle_reason_mappings); i++) {
@@ -2546,15 +2547,14 @@
snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "Motif %s", iks_name(text));
} else {
/* No technology specific information is available */
- cause_code = ast_malloc(data_size);
+ cause_code = ast_alloca(data_size);
+ memset(cause_code, 0, data_size);
}
ast_copy_string(cause_code->chan_name, ast_channel_name(chan), AST_CHANNEL_NAME);
cause_code->ast_cause = cause;
ast_queue_control_data(chan, AST_CONTROL_PVT_CAUSE_CODE, cause_code, data_size);
ast_channel_hangupcause_hash_set(chan, cause_code, data_size);
-
- ast_free(cause_code);
ast_debug(3, "Hanging up channel '%s' due to session terminate message with cause '%d'\n", ast_channel_name(chan), cause);
ast_queue_hangup_with_cause(chan, cause);
Modified: team/dlee/ASTERISK-22296/channels/chan_sip.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/chan_sip.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/chan_sip.c (original)
+++ team/dlee/ASTERISK-22296/channels/chan_sip.c Tue Aug 27 14:36:52 2013
@@ -10689,7 +10689,7 @@
/* Setup audio address and port */
if (p->rtp) {
- if (portno > 0) {
+ if (sa && portno > 0) {
start_ice(p->rtp);
ast_sockaddr_set_port(sa, portno);
ast_rtp_instance_set_remote_address(p->rtp, sa);
@@ -10737,7 +10737,7 @@
/* Setup video address and port */
if (p->vrtp) {
- if (vportno > 0) {
+ if (vsa && vportno > 0) {
start_ice(p->vrtp);
ast_sockaddr_set_port(vsa, vportno);
ast_rtp_instance_set_remote_address(p->vrtp, vsa);
@@ -10755,7 +10755,7 @@
/* Setup text address and port */
if (p->trtp) {
- if (tportno > 0) {
+ if (tsa && tportno > 0) {
start_ice(p->trtp);
ast_sockaddr_set_port(tsa, tportno);
ast_rtp_instance_set_remote_address(p->trtp, tsa);
@@ -10779,7 +10779,7 @@
/* Setup image address and port */
if (p->udptl) {
- if (udptlportno > 0) {
+ if (isa && udptlportno > 0) {
if (ast_test_flag(&p->flags[1], SIP_PAGE2_SYMMETRICRTP) && ast_test_flag(&p->flags[1], SIP_PAGE2_UDPTL_DESTINATION)) {
ast_rtp_instance_get_remote_address(p->rtp, isa);
if (!ast_sockaddr_isnull(isa) && debug) {
@@ -27988,6 +27988,7 @@
/* size of the string making up the cause code is "SIP " + cause length */
data_size += 4 + strlen(REQ_OFFSET_TO_STR(req, rlpart2));
cause_code = ast_alloca(data_size);
+ memset(cause_code, 0, data_size);
ast_copy_string(cause_code->chan_name, ast_channel_name(p->owner), AST_CHANNEL_NAME);
@@ -28167,7 +28168,7 @@
p->invitestate = INV_TERMINATED;
p->pendinginvite = 0;
acked = __sip_ack(p, seqno, 1 /* response */, 0);
- if (find_sdp(req)) {
+ if (p->owner && find_sdp(req)) {
if (process_sdp(p, req, SDP_T38_NONE)) {
return -1;
}
Modified: team/dlee/ASTERISK-22296/channels/sig_analog.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/sig_analog.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/sig_analog.c (original)
+++ team/dlee/ASTERISK-22296/channels/sig_analog.c Tue Aug 27 14:36:52 2013
@@ -2715,6 +2715,7 @@
subclass = analog_event2str(res);
data_size += strlen(subclass);
cause_code = ast_alloca(data_size);
+ memset(cause_code, 0, data_size);
cause_code->ast_cause = AST_CAUSE_NORMAL_CLEARING;
ast_copy_string(cause_code->chan_name, ast_channel_name(ast), AST_CHANNEL_NAME);
snprintf(cause_code->code, data_size - sizeof(*cause_code) + 1, "ANALOG %s", subclass);
Modified: team/dlee/ASTERISK-22296/channels/sig_pri.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/sig_pri.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/sig_pri.c (original)
+++ team/dlee/ASTERISK-22296/channels/sig_pri.c Tue Aug 27 14:36:52 2013
@@ -1404,6 +1404,7 @@
if (chan) {
int datalen = sizeof(*cause_code) + strlen(cause);
cause_code = ast_alloca(datalen);
+ memset(cause_code, 0, datalen);
cause_code->ast_cause = ast_cause;
ast_copy_string(cause_code->chan_name, ast_channel_name(chan), AST_CHANNEL_NAME);
ast_copy_string(cause_code->code, cause, datalen + 1 - sizeof(*cause_code));
Modified: team/dlee/ASTERISK-22296/channels/sig_ss7.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/channels/sig_ss7.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/channels/sig_ss7.c (original)
+++ team/dlee/ASTERISK-22296/channels/sig_ss7.c Tue Aug 27 14:36:52 2013
@@ -411,6 +411,7 @@
int datalen = sizeof(*cause_code) + strlen(cause);
cause_code = ast_alloca(datalen);
+ memset(cause_code, 0, datalen);
cause_code->ast_cause = ast_cause;
ast_copy_string(cause_code->chan_name, ast_channel_name(owner), AST_CHANNEL_NAME);
ast_copy_string(cause_code->code, cause, datalen + 1 - sizeof(*cause_code));
Modified: team/dlee/ASTERISK-22296/main/astmm.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/main/astmm.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/main/astmm.c (original)
+++ team/dlee/ASTERISK-22296/main/astmm.c Tue Aug 27 14:36:52 2013
@@ -142,6 +142,8 @@
static enum summary_opts atexit_summary;
/*! Nonzero if the unfreed regions are listed at exit. */
static int atexit_list;
+/*! Nonzero if the memory allocation backtrace is enabled. */
+static int backtrace_enabled;
#define HASH(a) (((unsigned long)(a)) % ARRAY_LEN(regions))
@@ -235,7 +237,7 @@
reg->cache = cache;
reg->lineno = lineno;
reg->which = which;
- reg->bt = ast_bt_create();
+ reg->bt = backtrace_enabled ? ast_bt_create() : NULL;
ast_copy_string(reg->file, file, sizeof(reg->file));
ast_copy_string(reg->func, func, sizeof(reg->func));
@@ -975,11 +977,49 @@
return CLI_SUCCESS;
}
+static char *handle_memory_backtrace(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "memory backtrace";
+ e->usage =
+ "Usage: memory backtrace {on|off}\n"
+ " Enable dumping an allocation backtrace with memory diagnostics.\n"
+ " Note that saving the backtrace data for each allocation\n"
+ " can be CPU intensive.\n";
+ return NULL;
+ case CLI_GENERATE:
+ if (a->pos == 2) {
+ const char * const options[] = { "off", "on", NULL };
+
+ return ast_cli_complete(a->word, options, a->n);
+ }
+ return NULL;
+ }
+
+ if (a->argc != 3) {
+ return CLI_SHOWUSAGE;
+ }
+
+ if (ast_true(a->argv[2])) {
+ backtrace_enabled = 1;
+ } else if (ast_false(a->argv[2])) {
+ backtrace_enabled = 0;
+ } else {
+ return CLI_SHOWUSAGE;
+ }
+
+ ast_cli(a->fd, "The memory backtrace is: %s\n", backtrace_enabled ? "On" : "Off");
+
+ return CLI_SUCCESS;
+}
+
static struct ast_cli_entry cli_memory[] = {
AST_CLI_DEFINE(handle_memory_atexit_list, "Enable memory allocations not freed at exit list."),
AST_CLI_DEFINE(handle_memory_atexit_summary, "Enable memory allocations not freed at exit summary."),
AST_CLI_DEFINE(handle_memory_show_allocations, "Display outstanding memory allocations"),
AST_CLI_DEFINE(handle_memory_show_summary, "Summarize outstanding memory allocations"),
+ AST_CLI_DEFINE(handle_memory_backtrace, "Enable dumping an allocation backtrace with memory diagnostics."),
};
AST_LIST_HEAD_NOLOCK(region_list, ast_region);
Modified: team/dlee/ASTERISK-22296/main/stasis_bridges.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/main/stasis_bridges.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/main/stasis_bridges.c (original)
+++ team/dlee/ASTERISK-22296/main/stasis_bridges.c Tue Aug 27 14:36:52 2013
@@ -132,6 +132,9 @@
static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_message *message);
static struct ast_manager_event_blob *blind_transfer_to_ami(struct stasis_message *message);
+static struct ast_json *ast_channel_entered_bridge_to_json(struct stasis_message *msg);
+static struct ast_json *ast_channel_left_bridge_to_json(struct stasis_message *msg);
+static struct ast_json *ast_bridge_merge_message_to_json(struct stasis_message *msg);
static struct stasis_cp_all *bridge_cache_all;
@@ -139,9 +142,12 @@
* @{ \brief Define bridge message types.
*/
STASIS_MESSAGE_TYPE_DEFN(ast_bridge_snapshot_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_bridge_merge_message_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_entered_bridge_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_left_bridge_type);
+STASIS_MESSAGE_TYPE_DEFN(ast_bridge_merge_message_type,
+ .to_json = ast_bridge_merge_message_to_json);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_entered_bridge_type,
+ .to_json = ast_channel_entered_bridge_to_json);
+STASIS_MESSAGE_TYPE_DEFN(ast_channel_left_bridge_type,
+ .to_json = ast_channel_left_bridge_to_json);
STASIS_MESSAGE_TYPE_DEFN(ast_blind_transfer_type, .to_ami = blind_transfer_to_ami);
STASIS_MESSAGE_TYPE_DEFN(ast_attended_transfer_type, .to_ami = attended_transfer_to_ami);
/*! @} */
@@ -305,6 +311,19 @@
ao2_ref(msg, +1);
return msg;
+}
+
+static struct ast_json *ast_bridge_merge_message_to_json(struct stasis_message *msg)
+{
+ struct ast_bridge_merge_message *merge;
+
+ merge = stasis_message_data(msg);
+
+ return ast_json_pack("{s: s, s: o, s: o, s: o}",
+ "type", "BridgeMerged",
+ "timestamp", ast_json_timeval(*stasis_message_timestamp(msg), NULL),
+ "bridge", ast_bridge_snapshot_to_json(merge->to),
+ "bridge_from", ast_bridge_snapshot_to_json(merge->from));
}
void ast_bridge_publish_merge(struct ast_bridge *to, struct ast_bridge *from)
@@ -415,6 +434,35 @@
/* state first, then leave blob (opposite of enter, preserves nesting of events) */
bridge_publish_state_from_blob(bridge, stasis_message_data(msg));
stasis_publish(ast_bridge_topic(bridge), msg);
+}
+
+static struct ast_json *simple_bridge_channel_event(
+ const char *type,
+ struct ast_bridge_snapshot *bridge_snapshot,
+ struct ast_channel_snapshot *channel_snapshot,
+ const struct timeval *tv)
+{
+ return ast_json_pack("{s: s, s: o, s: o, s: o}",
+ "type", type,
+ "timestamp", ast_json_timeval(*tv, NULL),
+ "bridge", ast_bridge_snapshot_to_json(bridge_snapshot),
+ "channel", ast_channel_snapshot_to_json(channel_snapshot));
+}
+
+struct ast_json *ast_channel_entered_bridge_to_json(struct stasis_message *msg)
+{
+ struct ast_bridge_blob *obj = stasis_message_data(msg);
+
+ return simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
+ obj->channel, stasis_message_timestamp(msg));
+}
+
+struct ast_json *ast_channel_left_bridge_to_json(struct stasis_message *msg)
+{
+ struct ast_bridge_blob *obj = stasis_message_data(msg);
+
+ return simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
+ obj->channel, stasis_message_timestamp(msg));
}
typedef struct ast_json *(*json_item_serializer_cb)(void *obj);
Modified: team/dlee/ASTERISK-22296/res/res_ari_asterisk.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_asterisk.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_asterisk.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_asterisk.c Tue Aug 27 14:36:52 2013
@@ -81,8 +81,16 @@
goto fin;
}
- args.only_count = ast_app_separate_args(
- args.only_parse, ',', vals, ARRAY_LEN(vals));
+ if (strlen(args.only_parse) == 0) {
+ /* ast_app_separate_args can't handle "" */
+ args.only_count = 1;
+ vals[0] = args.only_parse;
+ } else {
+ args.only_count = ast_app_separate_args(
+ args.only_parse, ',', vals,
+ ARRAY_LEN(vals));
+ }
+
if (args.only_count == 0) {
ast_ari_response_alloc_failed(response);
goto fin;
Modified: team/dlee/ASTERISK-22296/res/res_ari_bridges.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_bridges.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_bridges.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_bridges.c Tue Aug 27 14:36:52 2013
@@ -300,8 +300,16 @@
goto fin;
}
- args.channel_count = ast_app_separate_args(
- args.channel_parse, ',', vals, ARRAY_LEN(vals));
+ if (strlen(args.channel_parse) == 0) {
+ /* ast_app_separate_args can't handle "" */
+ args.channel_count = 1;
+ vals[0] = args.channel_parse;
+ } else {
+ args.channel_count = ast_app_separate_args(
+ args.channel_parse, ',', vals,
+ ARRAY_LEN(vals));
+ }
+
if (args.channel_count == 0) {
ast_ari_response_alloc_failed(response);
goto fin;
@@ -403,8 +411,16 @@
goto fin;
}
- args.channel_count = ast_app_separate_args(
- args.channel_parse, ',', vals, ARRAY_LEN(vals));
+ if (strlen(args.channel_parse) == 0) {
+ /* ast_app_separate_args can't handle "" */
+ args.channel_count = 1;
+ vals[0] = args.channel_parse;
+ } else {
+ args.channel_count = ast_app_separate_args(
+ args.channel_parse, ',', vals,
+ ARRAY_LEN(vals));
+ }
+
if (args.channel_count == 0) {
ast_ari_response_alloc_failed(response);
goto fin;
Modified: team/dlee/ASTERISK-22296/res/res_ari_events.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_ari_events.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_ari_events.c (original)
+++ team/dlee/ASTERISK-22296/res/res_ari_events.c Tue Aug 27 14:36:52 2013
@@ -90,8 +90,16 @@
goto fin;
}
- args.app_count = ast_app_separate_args(
- args.app_parse, ',', vals, ARRAY_LEN(vals));
+ if (strlen(args.app_parse) == 0) {
+ /* ast_app_separate_args can't handle "" */
+ args.app_count = 1;
+ vals[0] = args.app_parse;
+ } else {
+ args.app_count = ast_app_separate_args(
+ args.app_parse, ',', vals,
+ ARRAY_LEN(vals));
+ }
+
if (args.app_count == 0) {
ast_ari_response_alloc_failed(response);
goto fin;
@@ -127,14 +135,16 @@
* negotiation. Param parsing should happen earlier, but we
* need a way to pass it through the WebSocket code to the
* callback */
- RAII_VAR(char *, msg, NULL, ast_free);
+ RAII_VAR(char *, msg, NULL, ast_json_free);
if (response->message) {
msg = ast_json_dump_string(response->message);
} else {
- msg = ast_strdup("?");
+ ast_log(LOG_ERROR, "Missing response message\n");
}
- ast_websocket_write(ws_session, AST_WEBSOCKET_OPCODE_TEXT, msg,
- strlen(msg));
+ if (msg) {
+ ast_websocket_write(ws_session,
+ AST_WEBSOCKET_OPCODE_TEXT, msg, strlen(msg));
+ }
}
ast_free(args.app_parse);
ast_free(args.app);
Modified: team/dlee/ASTERISK-22296/res/res_stasis.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ASTERISK-22296/res/res_stasis.c?view=diff&rev=397834&r1=397833&r2=397834
==============================================================================
--- team/dlee/ASTERISK-22296/res/res_stasis.c (original)
+++ team/dlee/ASTERISK-22296/res/res_stasis.c Tue Aug 27 14:36:52 2013
@@ -87,6 +87,12 @@
#define CONTROLS_NUM_BUCKETS 127
/*!
+ * \brief Number of buckets for the Stasis bridges hash table. Remember to
+ * keep it a prime number!
+ */
+#define BRIDGES_NUM_BUCKETS 127
+
+/*!
* \brief Stasis application container.
*/
struct ao2_container *apps_registry;
@@ -96,12 +102,6 @@
struct ao2_container *app_bridges;
struct ao2_container *app_bridges_moh;
-
-/*! \brief Message router for the channel caching topic */
-struct stasis_message_router *channel_router;
-
-/*! \brief Message router for the bridge caching topic */
-struct stasis_message_router *bridge_router;
/*! AO2 hash function for \ref app */
static int app_hash(const void *obj, const int flags)
@@ -151,6 +151,30 @@
} else {
return 0;
}
+}
+
+static int cleanup_cb(void *obj, void *arg, int flags)
+{
+ struct app *app = obj;
+
+ if (!app_is_finished(app)) {
+ return 0;
+ }
+
+ ast_verb(1, "Shutting down application '%s'\n", app_name(app));
+ app_shutdown(app);
+
+ return CMP_MATCH;
+
+}
+
+/*!
+ * \brief Clean up any old apps that we don't need any more.
+ */
+static void cleanup(void)
+{
+ ao2_callback(apps_registry, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK,
+ cleanup_cb, NULL);
}
struct stasis_app_control *stasis_app_control_create(struct ast_channel *chan)
@@ -435,229 +459,6 @@
return ao2_find(app_bridges, bridge_id, OBJ_KEY);
}
-/*! \brief Typedef for blob handler callbacks */
-typedef struct ast_json *(*channel_blob_handler_cb)(struct ast_channel_blob *);
-
-/*! \brief Callback to check whether an app is watching a given channel */
-static int app_watching_channel_cb(void *obj, void *arg, int flags)
-{
- struct app *app = obj;
- char *uniqueid = arg;
-
- return app_is_watching_channel(app, uniqueid) ? CMP_MATCH : 0;
-}
-
-/*! \brief Get a container full of apps that are interested in the specified channel */
-static struct ao2_container *get_apps_watching_channel(const char *uniqueid)
-{
- struct ao2_container *watching_apps;
- char *uniqueid_dup;
- RAII_VAR(struct ao2_iterator *,watching_apps_iter, NULL, ao2_iterator_destroy);
- ast_assert(uniqueid != NULL);
-
- uniqueid_dup = ast_strdupa(uniqueid);
-
- watching_apps_iter = ao2_callback(apps_registry, OBJ_MULTIPLE, app_watching_channel_cb, uniqueid_dup);
- watching_apps = watching_apps_iter->c;
-
- if (!ao2_container_count(watching_apps)) {
- return NULL;
- }
-
- ao2_ref(watching_apps, +1);
- return watching_apps_iter->c;
-}
-
-/*! \brief Typedef for callbacks that get called on channel snapshot updates */
-typedef struct ast_json *(*channel_snapshot_monitor)(
- struct ast_channel_snapshot *old_snapshot,
- struct ast_channel_snapshot *new_snapshot,
- const struct timeval *tv);
-
-static struct ast_json *simple_channel_event(
- const char *type,
- struct ast_channel_snapshot *snapshot,
- const struct timeval *tv)
-{
- return ast_json_pack("{s: s, s: o, s: o}",
- "type", type,
- "timestamp", ast_json_timeval(*tv, NULL),
- "channel", ast_channel_snapshot_to_json(snapshot));
-}
-
-static struct ast_json *channel_created_event(
- struct ast_channel_snapshot *snapshot,
- const struct timeval *tv)
-{
- return simple_channel_event("ChannelCreated", snapshot, tv);
-}
-
-static struct ast_json *channel_destroyed_event(
- struct ast_channel_snapshot *snapshot,
- const struct timeval *tv)
-{
- return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
- "type", "ChannelDestroyed",
- "timestamp", ast_json_timeval(*tv, NULL),
- "cause", snapshot->hangupcause,
- "cause_txt", ast_cause2str(snapshot->hangupcause),
- "channel", ast_channel_snapshot_to_json(snapshot));
-}
-
-static struct ast_json *channel_state_change_event(
- struct ast_channel_snapshot *snapshot,
- const struct timeval *tv)
-{
- return simple_channel_event("ChannelStateChange", snapshot, tv);
-}
-
-/*! \brief Handle channel state changes */
-static struct ast_json *channel_state(
- struct ast_channel_snapshot *old_snapshot,
- struct ast_channel_snapshot *new_snapshot,
- const struct timeval *tv)
-{
- struct ast_channel_snapshot *snapshot = new_snapshot ? new_snapshot : old_snapshot;
-
- if (!old_snapshot) {
- return channel_created_event(snapshot, tv);
- } else if (!new_snapshot) {
- return channel_destroyed_event(snapshot, tv);
- } else if (old_snapshot->state != new_snapshot->state) {
- return channel_state_change_event(snapshot, tv);
- }
-
- return NULL;
-}
-
-static struct ast_json *channel_dialplan(
- struct ast_channel_snapshot *old_snapshot,
- struct ast_channel_snapshot *new_snapshot,
- const struct timeval *tv)
-{
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
-
- /* No Newexten event on cache clear */
- if (!new_snapshot) {
- return NULL;
- }
-
- /* Empty application is not valid for a Newexten event */
- if (ast_strlen_zero(new_snapshot->appl)) {
- return NULL;
- }
-
- if (old_snapshot && ast_channel_snapshot_cep_equal(old_snapshot, new_snapshot)) {
- return NULL;
- }
-
- return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}",
- "type", "ChannelDialplan",
- "timestamp", ast_json_timeval(*tv, NULL),
- "dialplan_app", new_snapshot->appl,
- "dialplan_app_data", new_snapshot->data,
- "channel", ast_channel_snapshot_to_json(new_snapshot));
-}
-
-static struct ast_json *channel_callerid(
- struct ast_channel_snapshot *old_snapshot,
- struct ast_channel_snapshot *new_snapshot,
- const struct timeval *tv)
-{
- RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
-
- /* No NewCallerid event on cache clear or first event */
- if (!old_snapshot || !new_snapshot) {
- return NULL;
- }
-
- if (ast_channel_snapshot_caller_id_equal(old_snapshot, new_snapshot)) {
- return NULL;
- }
-
- return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
- "type", "ChannelCallerId",
- "timestamp", ast_json_timeval(*tv, NULL),
- "caller_presentation", new_snapshot->caller_pres,
- "caller_presentation_txt", ast_describe_caller_presentation(
- new_snapshot->caller_pres),
- "channel", ast_channel_snapshot_to_json(new_snapshot));
-}
-
-channel_snapshot_monitor channel_monitors[] = {
- channel_state,
- channel_dialplan,
- channel_callerid
-};
-
-static int app_send_cb(void *obj, void *arg, int flags)
-{
- struct app *app = obj;
- struct ast_json *msg = arg;
-
- app_send(app, msg);
- return 0;
-}
-
-static void sub_channel_snapshot_handler(void *data,
- struct stasis_subscription *sub,
- struct stasis_topic *topic,
- struct stasis_message *message)
-{
- RAII_VAR(struct ao2_container *, watching_apps, NULL, ao2_cleanup);
- struct stasis_cache_update *update = stasis_message_data(message);
- struct ast_channel_snapshot *new_snapshot = stasis_message_data(update->new_snapshot);
- struct ast_channel_snapshot *old_snapshot = stasis_message_data(update->old_snapshot);
- /* Pull timestamp from the new snapshot, or from the update message
- * when there isn't one. */
- const struct timeval *tv = update->new_snapshot ? stasis_message_timestamp(update->new_snapshot) : stasis_message_timestamp(message);
- int i;
-
- watching_apps = get_apps_watching_channel(new_snapshot ? new_snapshot->uniqueid : old_snapshot->uniqueid);
- if (!watching_apps) {
- return;
- }
-
- for (i = 0; i < ARRAY_LEN(channel_monitors); ++i) {
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
-
- msg = channel_monitors[i](old_snapshot, new_snapshot, tv);
- if (msg) {
- ao2_callback(watching_apps, OBJ_NODATA, app_send_cb, msg);
- }
- }
-}
-
-static void distribute_message(struct ao2_container *apps, struct ast_json *msg)
-{
- ao2_callback(apps, OBJ_NODATA, app_send_cb, msg);
-}
-
-static void sub_channel_blob_handler(void *data,
- struct stasis_subscription *sub,
- struct stasis_topic *topic,
- struct stasis_message *message)
-{
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
- RAII_VAR(struct ao2_container *, watching_apps, NULL, ao2_cleanup);
- struct ast_channel_blob *obj = stasis_message_data(message);
-
- if (!obj->snapshot) {
- return;
- }
-
- msg = stasis_message_to_json(message);
- if (!msg) {
- return;
- }
-
- watching_apps = get_apps_watching_channel(obj->snapshot->uniqueid);
- if (!watching_apps) {
- return;
- }
-
- distribute_message(watching_apps, msg);
-}
/*!
* \brief In addition to running ao2_cleanup(), this function also removes the
@@ -709,7 +510,7 @@
ast_bridge_destroy(bridge, 0);
}
-int app_send_start_msg(struct app *app, struct ast_channel *chan,
+static int send_start_msg(struct app *app, struct ast_channel *chan,
int argc, char *argv[])
{
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
@@ -726,8 +527,9 @@
return -1;
}
- msg = ast_json_pack("{s: s, s: [], s: o}",
+ msg = ast_json_pack("{s: s, s: o, s: [], s: o}",
"type", "StasisStart",
+ "timestamp", ast_json_timeval(ast_tvnow(), NULL),
"args",
"channel", ast_channel_snapshot_to_json(snapshot));
if (!msg) {
@@ -750,7 +552,7 @@
return 0;
}
-int app_send_end_msg(struct app *app, struct ast_channel *chan)
+static int send_end_msg(struct app *app, struct ast_channel *chan)
{
RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
@@ -763,8 +565,9 @@
return -1;
}
- msg = ast_json_pack("{s: s, s: o}",
+ msg = 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));
if (!msg) {
return -1;
@@ -815,15 +618,17 @@
}
ao2_link(app_controls, control);
- res = app_send_start_msg(app, chan, argc, argv);
+ res = send_start_msg(app, chan, argc, argv);
if (res != 0) {
ast_log(LOG_ERROR,
"Error sending start message to '%s'\n", app_name);
- return res;
- }
-
- if (app_add_channel(app, chan)) {
- ast_log(LOG_ERROR, "Error adding listener for channel %s to app %s\n", ast_channel_name(chan), app_name);
+ return -1;
+ }
+
+ res = app_subscribe_channel(app, chan);
+ if (res != 0) {
+ ast_log(LOG_ERROR, "Error subscribing app '%s' to channel '%s'\n",
+ app_name, ast_channel_name(chan));
return -1;
}
@@ -831,13 +636,23 @@
RAII_VAR(struct ast_frame *, f, NULL, ast_frame_dtor);
int r;
int command_count;
+ struct ast_bridge *last_bridge = NULL;
+ struct ast_bridge *bridge = NULL;
/* Check to see if a bridge absorbed our hangup frame */
if (ast_check_hangup_locked(chan)) {
break;
}
- if (stasis_app_get_bridge(control)) {
+ last_bridge = bridge;
+ bridge = stasis_app_get_bridge(control);
+
+ if (bridge != last_bridge) {
+ app_unsubscribe_bridge(app, last_bridge);
+ app_subscribe_bridge(app, bridge);
+ }
+
+ if (bridge) {
/* Bridge is handling channel frames */
control_wait(control);
control_dispatch_all(control, chan);
@@ -882,13 +697,20 @@
}
}
- app_remove_channel(app, chan);
- res = app_send_end_msg(app, chan);
+ app_unsubscribe_bridge(app, stasis_app_get_bridge(control));
+ app_unsubscribe_channel(app, chan);
+
+ res = send_end_msg(app, chan);
if (res != 0) {
ast_log(LOG_ERROR,
"Error sending end message to %s\n", app_name);
return res;
}
+
+ /* There's an off chance that app is ready for cleanup. Go ahead
+ * and clean up, just in case
+ */
+ cleanup();
return res;
}
@@ -910,29 +732,6 @@
app_send(app, message);
return 0;
-}
-
-static int cleanup_cb(void *obj, void *arg, int flags)
-{
- struct app *app = obj;
-
- if (!app_is_finished(app)) {
- return 0;
- }
-
- ast_verb(1, "Cleaning up application '%s'\n", app_name(app));
-
- return CMP_MATCH;
-
-}
-
-/*!
- * \brief Clean up any old apps that we don't need any more.
- */
-static void cleanup(void)
-{
- ao2_callback(apps_registry, OBJ_MULTIPLE | OBJ_NODATA | OBJ_UNLINK,
- cleanup_cb, NULL);
}
int stasis_app_register(const char *app_name, stasis_app_cb handler, void *data)
@@ -994,249 +793,22 @@
ast_module_unref(ast_module_info->self);
}
-/*! \brief Callback to check whether an app is watching a given bridge */
-static int app_watching_bridge_cb(void *obj, void *arg, int flags)
-{
- struct app *app = obj;
- char *uniqueid = arg;
-
- return app_is_watching_bridge(app, uniqueid) ? CMP_MATCH : 0;
-}
-
-/*! \brief Get a container full of apps that are interested in the specified bridge */
-static struct ao2_container *get_apps_watching_bridge(const char *uniqueid)
-{
- struct ao2_container *watching_apps;
- char *uniqueid_dup;
- RAII_VAR(struct ao2_iterator *,watching_apps_iter, NULL, ao2_iterator_destroy);
- ast_assert(uniqueid != NULL);
-
- uniqueid_dup = ast_strdupa(uniqueid);
-
- watching_apps_iter = ao2_callback(apps_registry, OBJ_MULTIPLE, app_watching_bridge_cb, uniqueid_dup);
- watching_apps = watching_apps_iter->c;
-
- if (!ao2_container_count(watching_apps)) {
- return NULL;
- }
-
- ao2_ref(watching_apps, +1);
- return watching_apps_iter->c;
-}
-
-/*! Callback used to remove an app's interest in a bridge */
-static int remove_bridge_cb(void *obj, void *arg, int flags)
-{
- app_remove_bridge(obj, arg);
- return 0;
-}
-
-static struct ast_json *simple_bridge_event(
- const char *type,
- struct ast_bridge_snapshot *snapshot,
- const struct timeval *tv)
-{
- return ast_json_pack("{s: s, s: o, s: o}",
- "type", type,
- "timestamp", ast_json_timeval(*tv, NULL),
- "bridge", ast_bridge_snapshot_to_json(snapshot));
-}
-
-static struct ast_json *simple_bridge_channel_event(
- const char *type,
- struct ast_bridge_snapshot *bridge_snapshot,
- struct ast_channel_snapshot *channel_snapshot,
- const struct timeval *tv)
-{
- return ast_json_pack("{s: s, s: o, s: o, s: o}",
- "type", type,
- "timestamp", ast_json_timeval(*tv, NULL),
- "bridge", ast_bridge_snapshot_to_json(bridge_snapshot),
- "channel", ast_channel_snapshot_to_json(channel_snapshot));
-}
-
-static void sub_bridge_snapshot_handler(void *data,
- struct stasis_subscription *sub,
- struct stasis_topic *topic,
- struct stasis_message *message)
-{
- RAII_VAR(struct ao2_container *, watching_apps, NULL, ao2_cleanup);
- struct stasis_cache_update *update = stasis_message_data(message);
- struct ast_bridge_snapshot *new_snapshot = stasis_message_data(update->new_snapshot);
- struct ast_bridge_snapshot *old_snapshot = stasis_message_data(update->old_snapshot);
- const struct timeval *tv = update->new_snapshot ? stasis_message_timestamp(update->new_snapshot) : stasis_message_timestamp(message);
-
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
-
- watching_apps = get_apps_watching_bridge(new_snapshot ? new_snapshot->uniqueid : old_snapshot->uniqueid);
- if (!watching_apps || !ao2_container_count(watching_apps)) {
- return;
- }
-
- if (!new_snapshot) {
- RAII_VAR(char *, bridge_id, ast_strdup(old_snapshot->uniqueid), ast_free);
-
- /* The bridge has gone away. Create the message, make sure no apps are
- * watching this bridge anymore, and destroy the bridge's control
- * structure */
- msg = simple_bridge_event("BridgeDestroyed", old_snapshot, tv);
- ao2_callback(watching_apps, OBJ_NODATA, remove_bridge_cb, bridge_id);
- stasis_app_bridge_destroy(old_snapshot->uniqueid);
- } else if (!old_snapshot) {
- msg = simple_bridge_event("BridgeCreated", old_snapshot, tv);
- }
-
- if (!msg) {
- return;
- }
-
- distribute_message(watching_apps, msg);
-}
-
-/*! \brief Callback used to merge two containers of applications */
-static int list_merge_cb(void *obj, void *arg, int flags)
-{
- /* remove any current entries for this app */
- ao2_find(arg, obj, OBJ_POINTER | OBJ_UNLINK | OBJ_NODATA | OBJ_MULTIPLE);
- /* relink as the only entry */
- ao2_link(arg, obj);
- return 0;
-}
-
-/*! \brief Merge container src into container dst without modifying src */
-static void update_apps_list(struct ao2_container *dst, struct ao2_container *src)
-{
- ao2_callback(src, OBJ_NODATA, list_merge_cb, dst);
-}
-
-/*! \brief Callback for adding to an app's bridges of interest */
-static int app_add_bridge_cb(void *obj, void *arg, int flags)
-{
- app_add_bridge(obj, arg);
- return 0;
-}
-
-/*! \brief Add interest in the given bridge to all apps in the container */
-static void update_bridge_interest(struct ao2_container *apps, const char *bridge_id)
-{
- RAII_VAR(char *, bridge_id_dup, ast_strdup(bridge_id), ast_free);
- ao2_callback(apps, OBJ_NODATA, app_add_bridge_cb, bridge_id_dup);
-}
-
-static void sub_bridge_merge_handler(void *data,
- struct stasis_subscription *sub,
- struct stasis_topic *topic,
- struct stasis_message *message)
-{
- RAII_VAR(struct ao2_container *, watching_apps_to, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, watching_apps_from, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, watching_apps_all, ao2_container_alloc(1, NULL, NULL), ao2_cleanup);
- struct ast_bridge_merge_message *merge = stasis_message_data(message);
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
- RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
- const struct timeval *tv = stasis_message_timestamp(message);
-
- watching_apps_to = get_apps_watching_bridge(merge->to->uniqueid);
- if (watching_apps_to) {
- update_apps_list(watching_apps_all, watching_apps_to);
- }
-
- watching_apps_from = get_apps_watching_bridge(merge->from->uniqueid);
- if (watching_apps_from) {
- update_bridge_interest(watching_apps_from, merge->to->uniqueid);
- update_apps_list(watching_apps_all, watching_apps_from);
- }
-
- if (!ao2_container_count(watching_apps_all)) {
- return;
- }
-
- msg = ast_json_pack("{s: s, s: o, s: o, s: o}",
- "type", "BridgeMerged",
- "timestamp", ast_json_timeval(*tv, NULL),
- "bridge", ast_bridge_snapshot_to_json(merge->to),
- "bridge_from", ast_bridge_snapshot_to_json(merge->from));
-
- if (!msg) {
- return;
- }
-
- distribute_message(watching_apps_all, msg);
-}
-
-static void sub_bridge_enter_handler(void *data,
- struct stasis_subscription *sub,
- struct stasis_topic *topic,
- struct stasis_message *message)
-{
- RAII_VAR(struct ao2_container *, watching_apps_channel, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, watching_apps_bridge, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, watching_apps_all, ao2_container_alloc(1, NULL, NULL), ao2_cleanup);
- struct ast_bridge_blob *obj = stasis_message_data(message);
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
-
- watching_apps_bridge = get_apps_watching_bridge(obj->bridge->uniqueid);
- if (watching_apps_bridge) {
- update_apps_list(watching_apps_all, watching_apps_bridge);
- }
-
- watching_apps_channel = get_apps_watching_channel(obj->channel->uniqueid);
- if (watching_apps_channel) {
- update_bridge_interest(watching_apps_channel, obj->bridge->uniqueid);
- update_apps_list(watching_apps_all, watching_apps_channel);
- }
-
- if (!ao2_container_count(watching_apps_all)) {
- return;
- }
-
- msg = simple_bridge_channel_event("ChannelEnteredBridge", obj->bridge,
- obj->channel, stasis_message_timestamp(message));
-
- distribute_message(watching_apps_all, msg);
-}
-
-static void sub_bridge_leave_handler(void *data,
- struct stasis_subscription *sub,
- struct stasis_topic *topic,
- struct stasis_message *message)
-{
- RAII_VAR(struct ao2_container *, watching_apps_bridge, NULL, ao2_cleanup);
- struct ast_bridge_blob *obj = stasis_message_data(message);
- RAII_VAR(struct ast_json *, msg, NULL, ast_json_unref);
-
- watching_apps_bridge = get_apps_watching_bridge(obj->bridge->uniqueid);
- if (!watching_apps_bridge) {
- return;
- }
-
- msg = simple_bridge_channel_event("ChannelLeftBridge", obj->bridge,
- obj->channel, stasis_message_timestamp(message));
-
- distribute_message(watching_apps_bridge, msg);
-}
-
static int load_module(void)
{
- int r = 0;
-
- apps_registry =
- ao2_container_alloc(APPS_NUM_BUCKETS, app_hash, app_compare);
+ apps_registry = ao2_container_alloc(APPS_NUM_BUCKETS, app_hash,
+ app_compare);
if (apps_registry == NULL) {
return AST_MODULE_LOAD_FAILURE;
}
- app_controls = ao2_container_alloc(CONTROLS_NUM_BUCKETS,
- control_hash, control_compare);
+ app_controls = ao2_container_alloc(CONTROLS_NUM_BUCKETS, control_hash,
+ control_compare);
if (app_controls == NULL) {
return AST_MODULE_LOAD_FAILURE;
}
- app_bridges = ao2_container_alloc(CONTROLS_NUM_BUCKETS,
- bridges_hash, bridges_compare);
[... 1021 lines stripped ...]
More information about the asterisk-commits
mailing list