[svn-commits] rmudgett: branch 13 r431974 - /branches/13/main/aoc.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Feb 19 12:25:45 CST 2015


Author: rmudgett
Date: Thu Feb 19 12:25:36 2015
New Revision: 431974

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=431974
Log:
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/

Modified:
    branches/13/main/aoc.c

Modified: branches/13/main/aoc.c
URL: http://svnview.digium.com/svn/asterisk/branches/13/main/aoc.c?view=diff&rev=431974&r1=431973&r2=431974
==============================================================================
--- branches/13/main/aoc.c (original)
+++ branches/13/main/aoc.c Thu Feb 19 12:25:36 2015
@@ -1793,24 +1793,87 @@
 			     "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);
-
-	if (!(channel = ast_manager_build_channel_state_string(
-		      obj->snapshot))) {
-		return NULL;
-	}
-
-	if (!(aoc = ast_manager_str_from_json_object(obj->blob, NULL))) {
-		return NULL;
-	}
-
-	return ast_manager_event_blob_create(EVENT_FLAG_AOC, event_name, "%s%s",
-					     AS_OR(channel, ""), ast_str_buffer(aoc));
+	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 (aoc_event->snapshot) {
+		channel = ast_manager_build_channel_state_string(aoc_event->snapshot);
+		if (!channel) {
+			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));
+	}
+
+	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 @@
 
 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 @@
 		return 0;
 	}
 
-	ast_channel_publish_cached_blob(chan, msg_type, blob);
+	aoc_publish_blob(chan, msg_type, blob);
+	ast_json_unref(blob);
 	return 0;
 }
 




More information about the svn-commits mailing list