diff options
author | Richard Mudgett <rmudgett@digium.com> | 2015-02-19 18:25:36 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2015-02-19 18:25:36 +0000 |
commit | 40547e7210d5ca2ba651bbcdb7af50eb330a5ed8 (patch) | |
tree | caa3f82e4eeab5cb2da7c4bd1478ccc2d6bfbd5e | |
parent | 2181c9443f4c43d0c463151f0930b8a8af888c1d (diff) |
ISDN AOC: Fix crash from an AOC-E message that doesn't have a channel association.
Processing an AOC-E event that does not or no longer has a channel
association causes a crash.
The problem with posting AOC events to the channel topic is that AOC-E
events don't always have a channel association and posting the event to
the all channels topic is just wrong. AOC-E events do however have their
own charging association method to refer to the agreement with the
charging entity.
* Changed the AOC events to post to the AMI manager topic instead of the
channel topics. If a channel is associated with the event then channel
snapshot information is supplied with the AMI event.
* Eliminated RAII_VAR() usage in aoc_to_ami() and ast_aoc_manager_event().
This patch supercedes the patch on Review: https://reviewboard.asterisk.org/r/4427/
ASTERISK-22670 #close
Reported by: klaus3000
ASTERISK-24689 #close
Reported by: Marcel Manz
ASTERISK-24740 #close
Reported by: Panos Gkikakis
Review: https://reviewboard.asterisk.org/r/4430/
git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@431974 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r-- | main/aoc.c | 88 |
1 files changed, 76 insertions, 12 deletions
diff --git a/main/aoc.c b/main/aoc.c index de43efcb5..b66f2dea8 100644 --- a/main/aoc.c +++ b/main/aoc.c @@ -1793,24 +1793,87 @@ static struct ast_json *e_to_json(const struct ast_aoc_decoded *decoded) "Charge", charge_to_json(decoded)); } +struct aoc_event_blob { + /*! Channel AOC event is associated with (NULL for unassociated) */ + struct ast_channel_snapshot *snapshot; + /*! AOC JSON blob of data */ + struct ast_json *blob; +}; + +static void aoc_event_blob_dtor(void *obj) +{ + struct aoc_event_blob *aoc_event = obj; + + ao2_cleanup(aoc_event->snapshot); + ast_json_unref(aoc_event->blob); +} + +/*! + * \internal + * \brief Publish an AOC event. + * \since 13.3.0 + * + * \param chan Channel associated with the AOC event. (May be NULL if no channel) + * \param msg_type What kind of AOC event. + * \param blob AOC data blob to publish. + * + * \return Nothing + */ +static void aoc_publish_blob(struct ast_channel *chan, struct stasis_message_type *msg_type, struct ast_json *blob) +{ + struct stasis_message *msg; + struct aoc_event_blob *aoc_event; + + if (!blob || ast_json_is_null(blob)) { + /* No AOC blob information? Nothing to send an event about. */ + return; + } + + aoc_event = ao2_alloc_options(sizeof(*aoc_event), aoc_event_blob_dtor, + AO2_ALLOC_OPT_LOCK_NOLOCK); + if (!aoc_event) { + return; + } + + if (chan) { + aoc_event->snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan)); + if (!aoc_event->snapshot) { + ao2_ref(aoc_event, -1); + return; + } + } + aoc_event->blob = ast_json_ref(blob); + + msg = stasis_message_create(msg_type, aoc_event); + ao2_ref(aoc_event, -1); + + stasis_publish(ast_manager_get_topic(), msg); +} + static struct ast_manager_event_blob *aoc_to_ami(struct stasis_message *message, const char *event_name) { - struct ast_channel_blob *obj = stasis_message_data(message); - RAII_VAR(struct ast_str *, channel, NULL, ast_free); - RAII_VAR(struct ast_str *, aoc, NULL, ast_free); + struct aoc_event_blob *aoc_event = stasis_message_data(message); + struct ast_str *channel = NULL; + struct ast_str *aoc; + struct ast_manager_event_blob *ev = NULL; - if (!(channel = ast_manager_build_channel_state_string( - obj->snapshot))) { - return NULL; + if (aoc_event->snapshot) { + channel = ast_manager_build_channel_state_string(aoc_event->snapshot); + if (!channel) { + return NULL; + } } - if (!(aoc = ast_manager_str_from_json_object(obj->blob, NULL))) { - return NULL; + aoc = ast_manager_str_from_json_object(aoc_event->blob, NULL); + if (aoc && !ast_strlen_zero(ast_str_buffer(aoc))) { + ev = ast_manager_event_blob_create(EVENT_FLAG_AOC, event_name, "%s%s", + AS_OR(channel, ""), ast_str_buffer(aoc)); } - return ast_manager_event_blob_create(EVENT_FLAG_AOC, event_name, "%s%s", - AS_OR(channel, ""), ast_str_buffer(aoc)); + ast_free(aoc); + ast_free(channel); + return ev; } static struct ast_manager_event_blob *aoc_s_to_ami(struct stasis_message *message) @@ -1846,7 +1909,7 @@ STASIS_MESSAGE_TYPE_DEFN( int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_channel *chan) { - RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref); + struct ast_json *blob; struct stasis_message_type *msg_type; if (!decoded) { @@ -1871,7 +1934,8 @@ int ast_aoc_manager_event(const struct ast_aoc_decoded *decoded, struct ast_chan return 0; } - ast_channel_publish_cached_blob(chan, msg_type, blob); + aoc_publish_blob(chan, msg_type, blob); + ast_json_unref(blob); return 0; } |