[asterisk-commits] mjordan: branch mjordan/ami-refactoring r388029 - in /team/mjordan/ami-refact...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed May 8 14:22:18 CDT 2013


Author: mjordan
Date: Wed May  8 14:22:16 2013
New Revision: 388029

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388029
Log:
Drop in the fax changes

Modified:
    team/mjordan/ami-refactoring/CHANGES
    team/mjordan/ami-refactoring/apps/app_fax.c
    team/mjordan/ami-refactoring/include/asterisk/stasis_channels.h
    team/mjordan/ami-refactoring/main/manager_channels.c
    team/mjordan/ami-refactoring/main/stasis_channels.c
    team/mjordan/ami-refactoring/res/res_fax.c

Modified: team/mjordan/ami-refactoring/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/ami-refactoring/CHANGES?view=diff&rev=388029&r1=388028&r2=388029
==============================================================================
--- team/mjordan/ami-refactoring/CHANGES (original)
+++ team/mjordan/ami-refactoring/CHANGES Wed May  8 14:22:16 2013
@@ -68,6 +68,9 @@
    fail to receive this event due to being connected after modules have loaded.
    AMI connections that want to know when Asterisk is ready should listen for
    the "FullyBooted" event.
+
+ * app_fax now sends the same send fax/receive fax events as res_fax. The "FaxSent" event
+   is now the "SendFAX" event, and the "FaxReceived" event is now the "ReceivedFAX" event.
 
 Channel Drivers
 ------------------

Modified: team/mjordan/ami-refactoring/apps/app_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/ami-refactoring/apps/app_fax.c?view=diff&rev=388029&r1=388028&r2=388029
==============================================================================
--- team/mjordan/ami-refactoring/apps/app_fax.c (original)
+++ team/mjordan/ami-refactoring/apps/app_fax.c Wed May  8 14:22:16 2013
@@ -43,7 +43,8 @@
 #include "asterisk/app.h"
 #include "asterisk/dsp.h"
 #include "asterisk/module.h"
-#include "asterisk/manager.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_channels.h"
 
 /*** DOCUMENTATION
 	<application name="SendFAX" language="en_US" module="app_fax">

Modified: team/mjordan/ami-refactoring/include/asterisk/stasis_channels.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/ami-refactoring/include/asterisk/stasis_channels.h?view=diff&rev=388029&r1=388028&r2=388029
==============================================================================
--- team/mjordan/ami-refactoring/include/asterisk/stasis_channels.h (original)
+++ team/mjordan/ami-refactoring/include/asterisk/stasis_channels.h Wed May  8 14:22:16 2013
@@ -140,6 +140,18 @@
 
 /*!
  * \since 12
+ * \brief Obtain the latest \ref ast_channel_snapshot from the \ref stasis cache. This is
+ * an ao2 object, so use \ref ao2_cleanup() to deallocate.
+ *
+ * \param unique_id The channel's unique ID
+ *
+ * \retval A \ref ast_channel_snapshot on success
+ * \retval NULL on error
+ */
+struct ast_channel_snapshot *ast_channel_get_cached_snapshot(const char *uniqueid);
+
+/*!
+ * \since 12
  * \brief Creates a \ref ast_channel_blob message.
  *
  * The \a blob JSON object requires a \c "type" field describing the blob. It
@@ -152,6 +164,23 @@
  * \return \c NULL on error
  */
 struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
+					       struct ast_json *blob);
+
+/*!
+ * \since 12
+ * \brief Creates a \ref ast_channel_blob message using the current cached
+ * \ref ast_channel_snapshot for the passed in \ref ast_channel
+ *
+ * The \a blob JSON object requires a \c "type" field describing the blob. It
+ * should also be treated as immutable and not modified after it is put into the
+ * message.
+ *
+ * \param chan Channel blob is associated with
+ * \param blob JSON object representing the data.
+ * \return \ref ast_channel_blob message.
+ * \return \c NULL on error
+ */
+struct stasis_message *ast_channel_cached_blob_create(struct ast_channel *chan,
 					       struct ast_json *blob);
 
 /*!

Modified: team/mjordan/ami-refactoring/main/manager_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/ami-refactoring/main/manager_channels.c?view=diff&rev=388029&r1=388028&r2=388029
==============================================================================
--- team/mjordan/ami-refactoring/main/manager_channels.c (original)
+++ team/mjordan/ami-refactoring/main/manager_channels.c Wed May  8 14:22:16 2013
@@ -366,6 +366,66 @@
 				<ref type="managerEvent">HangupHandlerPop</ref>
 				<ref type="function">CHANNEL</ref>
 			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="FAXStatus">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>
+				Raised periodically during a fax transmission.
+			</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Operation">
+					<enumlist>
+						<enum name="gateway"/>
+						<enum name="receive"/>
+						<enum name="send"/>
+					</enumlist>
+				</parameter>
+				<parameter name="Status">
+					<para>A text message describing the current status of the fax</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ReceiveFAX']/managerEventInstance/syntax/parameter[@name='LocalStationID'])" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ReceiveFAX']/managerEventInstance/syntax/parameter[@name='Filename'])" />
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ReceiveFAX">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>
+				Raised when a receive fax operation has completed.
+			</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="LocalStationID">
+					<para>The value of the <variable>LOCALSTATIONID</variable> channel variable</para>
+				<parameter>
+				<parameter name="RemoteStationID">
+					<para>The value of the <variable>REMOTESTATIONID</variable> channel variable</para>
+				<parameter>
+				<parameter name="PagesTransferred">
+					<para>The number of pages that have been transferred</para>
+				</parameter>
+				<parameter name="Resolution">
+					<para>The negotiated resolution</para>
+				<parameter>
+				<parameter name="TransferRate">
+					<para>The negotiated transfer rate</para>
+				</parameter>
+				<parameter name="FileName" multiple="yes">
+					<para>The files being affected by the fax operation</para>
+				</parameter>
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="SendFAX">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>
+				Raised when a send fax operation has completed.
+			</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ReceiveFAX']/managerEventInstance/syntax/parameter)" />
+			</syntax>
 		</managerEventInstance>
 	</managerEvent>
  ***/
@@ -962,6 +1022,77 @@
 		handler);
 }
 
+static void channel_fax_handler(struct ast_channel_blob *obj)
+{
+	RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
+	RAII_VAR(struct ast_str *, event_buffer, ast_str_create(256), ast_free);
+	const char *subtype = ast_json_string_get(ast_json_object_get(obj->blob, "subtype"));
+	struct ast_json *operation = ast_json_object_get(obj->blob, "operation");
+	struct ast_json *status = ast_json_object_get(obj->blob, "status");
+	struct ast_json *local_station_id = ast_json_object_get(obj->blob, "local_station_id");
+	struct ast_json *remote_station_id = ast_json_object_get(obj->blob, "remote_station_id");
+	struct ast_json *fax_pages = ast_json_object_get(obj->blob, "fax_pages");
+	struct ast_json *fax_resolution = ast_json_object_get(obj->blob, "fax_resolution");
+	struct ast_json *fax_bitrate = ast_json_object_get(obj->blob, "fax_bitrate");
+	struct ast_json *filenames = ast_json_object_get(obj->blob, "filenames");
+	const char *event;
+	size_t array_len;
+	size_t i;
+
+	if (!event_buffer) {
+		return;
+	}
+
+	channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
+	if (!channel_event_string) {
+		return;
+	}
+
+	if (!strcmp(subtype, "status")) {
+		event = "FAXStatus";
+	} else if (!strcmp(subtype, "status")) {
+		event = "ReceiveFAX";
+	} else if (!strcmp(subtype, "status")) {
+		event = "SendFAX";
+	} else {
+		return;
+	}
+
+	if (operation) {
+		ast_str_append(&event_buffer, 0, "Operation: %s\r\n", ast_json_string_get(operation));
+	}
+	if (status) {
+		ast_str_append(&event_buffer, 0, "Status: %s\r\n", ast_json_string_get(status));
+	}
+	if (local_station_id) {
+		ast_str_append(&event_buffer, 0, "LocalStationID: %s\r\n", ast_json_string_get(local_station_id));
+	}
+	if (remote_station_id) {
+		ast_str_append(&event_buffer, 0, "RemoteStationID: %s\r\n", ast_json_string_get(remote_station_id));
+	}
+	if (fax_pages) {
+		ast_str_append(&event_buffer, 0, "PagesTransferred: %s\r\n", ast_json_string_get(fax_pages));
+	}
+	if (fax_resolution) {
+		ast_str_append(&event_buffer, 0, "Resolution: %s\r\n", ast_json_string_get(fax_resolution));
+	}
+	if (fax_bitrate) {
+		ast_str_append(&event_buffer, 0, "TransferRate: %s\r\n", ast_json_string_get(fax_bitrate));
+	}
+	if (filenames) {
+		array_len = ast_json_array_size(filenames);
+		for (i = 0; i < array_len; i++) {
+			ast_str_append(&event_buffer, 0, "FileName: %s\r\n", ast_json_string_get(ast_json_array_get(filenames, i)));
+		}
+	}
+
+	manager_event(EVENT_FLAG_CALL, event,
+		"%s"
+		"%s",
+		channel_event_string,
+		ast_str_buffer(event_buffer));
+}
+
 /*!
  * \brief Callback processing messages on the channel topic.
  */
@@ -983,6 +1114,8 @@
 		channel_dtmf_end(obj);
 	} else if (strcmp("hangup_handler", ast_channel_blob_json_type(obj)) == 0) {
 		channel_hangup_handler(obj);
+	} else if (strcmp("fax", ast_channel_blob_json_type(obj)) == 0) {
+		channel_fax_handler(obj);
 	}
 }
 

Modified: team/mjordan/ami-refactoring/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/ami-refactoring/main/stasis_channels.c?view=diff&rev=388029&r1=388028&r2=388029
==============================================================================
--- team/mjordan/ami-refactoring/main/stasis_channels.c (original)
+++ team/mjordan/ami-refactoring/main/stasis_channels.c Wed May  8 14:22:16 2013
@@ -228,11 +228,11 @@
 	publish_message_for_channel_topics(msg, caller);
 }
 
-struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
-					       struct ast_json *blob)
-{
+static struct stasis_message *create_channel_blob_message(struct ast_channel_snapshot *snapshot,
+		struct ast_json *blob)
+{
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_channel_blob *, obj, NULL, ao2_cleanup);
-	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
 	struct ast_json *type;
 
 	ast_assert(blob != NULL);
@@ -248,13 +248,10 @@
 		return NULL;
 	}
 
-	if (chan) {
-		obj->snapshot = ast_channel_snapshot_create(chan);
-		if (obj->snapshot == NULL) {
-			return NULL;
-		}
-	}
-
+	if (snapshot) {
+		obj->snapshot = snapshot;
+		ao2_ref(obj->snapshot, +1);
+	}
 	obj->blob = ast_json_ref(blob);
 
 	msg = stasis_message_create(ast_channel_blob_type(), obj);
@@ -264,6 +261,28 @@
 
 	ao2_ref(msg, +1);
 	return msg;
+}
+
+struct stasis_message *ast_channel_cached_blob_create(struct ast_channel *chan,
+					       struct ast_json *blob)
+{
+	RAII_VAR(struct ast_channel_snapshot *, snapshot,
+			ast_channel_get_cached_snapshot(ast_channel_uniqueid(chan)),
+			ao2_cleanup);
+
+	return create_channel_blob_message(snapshot, blob);
+}
+
+struct stasis_message *ast_channel_blob_create(struct ast_channel *chan,
+					       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, blob);
 }
 
 const char *ast_channel_blob_json_type(struct ast_channel_blob *obj)
@@ -351,6 +370,25 @@
 
 	ao2_ref(obj, +1);
 	return obj;
+}
+
+struct ast_channel_snapshot *ast_channel_get_cached_snapshot(const char *uniqueid)
+{
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	struct ast_channel_snapshot *snapshot;
+
+	ast_assert(!ast_strlen_zero(uniqueid));
+
+	message = stasis_cache_get(ast_channel_topic_all_cached(),
+			ast_channel_snapshot_type(),
+			uniqueid);
+	if (!message) {
+		return NULL;
+	}
+
+	snapshot = stasis_message_data(message);
+	ao2_ref(snapshot, +1);
+	return snapshot;
 }
 
 static void channel_role_snapshot_dtor(void *obj)

Modified: team/mjordan/ami-refactoring/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/ami-refactoring/res/res_fax.c?view=diff&rev=388029&r1=388028&r2=388029
==============================================================================
--- team/mjordan/ami-refactoring/res/res_fax.c (original)
+++ team/mjordan/ami-refactoring/res/res_fax.c Wed May  8 14:22:16 2013
@@ -83,11 +83,12 @@
 #include "asterisk/file.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
-#include "asterisk/manager.h"
 #include "asterisk/dsp.h"
 #include "asterisk/indications.h"
 #include "asterisk/ast_version.h"
 #include "asterisk/translate.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_channels.h"
 
 /*** DOCUMENTATION
 	<application name="ReceiveFAX" language="en_US" module="res_fax">
@@ -384,12 +385,6 @@
 	AST_APP_OPTION('z', OPT_REQUEST_T38),
 END_OPTIONS);
 
-struct manager_event_info {
-	char context[AST_MAX_CONTEXT];
-	char exten[AST_MAX_EXTENSION];
-	char cid[128];
-};
-
 static void debug_check_frame_for_silence(struct ast_fax_session *s, unsigned int c2s, struct ast_frame *frame)
 {
 	struct debug_info_history *history = c2s ? &s->debug_info->c2s : &s->debug_info->s2c;
@@ -1091,13 +1086,39 @@
 	return s;
 }
 
-static void get_manager_event_info(struct ast_channel *chan, struct manager_event_info *info)
-{
-	pbx_substitute_variables_helper(chan, "${CONTEXT}", info->context, sizeof(info->context));
-	pbx_substitute_variables_helper(chan, "${EXTEN}", info->exten, sizeof(info->exten));
-	pbx_substitute_variables_helper(chan, "${CALLERID(num)}", info->cid, sizeof(info->cid));
-}
-
+/*!
+ * \internal
+ * \brief Convert the filenames in a fax session into a JSON array
+ * \retval NULL on error
+ * \retval A \ref ast_json array on success
+ */
+static struct ast_json *generate_filenames_json(struct ast_fax_session_details *details)
+{
+	RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
+	struct ast_fax_document *doc;
+
+	if (!details || !json_array) {
+		return NULL;
+	}
+
+	/* don't process empty lists */
+	if (AST_LIST_EMPTY(&details->documents)) {
+		return NULL;
+	}
+
+	AST_LIST_TRAVERSE(&details->documents, doc, next) {
+		struct ast_json *entry = ast_json_string_create(doc->filename);
+		if (!entry) {
+			return NULL;
+		}
+		if (ast_json_array_append(json_array, entry)) {
+			return NULL;
+		}
+	}
+
+	ast_json_ref(json_array);
+	return json_array;
+}
 
 /* \brief Generate a string of filenames using the given prefix and separator.
  * \param details the fax session details
@@ -1149,39 +1170,40 @@
 /*! \brief send a FAX status manager event */
 static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details, const char *status)
 {
-	char *filenames = generate_filenames_string(details, "FileName: ", "\r\n");
-
-	ast_channel_lock(chan);
-	if (details->option.statusevents) {
-		struct manager_event_info info;
-
-		get_manager_event_info(chan, &info);
-		manager_event(EVENT_FLAG_CALL,
-			      "FAXStatus",
-			      "Operation: %s\r\n"
-			      "Status: %s\r\n"
-			      "Channel: %s\r\n"
-			      "Context: %s\r\n"
-			      "Exten: %s\r\n"
-			      "CallerID: %s\r\n"
-			      "LocalStationID: %s\r\n"
-			      "%s%s",
-			      (details->caps & AST_FAX_TECH_GATEWAY) ? "gateway" : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
-			      status,
-			      ast_channel_name(chan),
-			      info.context,
-			      info.exten,
-			      info.cid,
-			      details->localstationid,
-			      S_OR(filenames, ""),
-			      filenames ? "\r\n" : "");
-	}
-	ast_channel_unlock(chan);
-
-	if (filenames) {
-		ast_free(filenames);
-	}
-
+	RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
+	RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	struct ast_json *json_filenames = NULL;
+
+	if (!details->option.statusevents) {
+		return 0;
+	}
+
+	json_filenames = generate_filenames_json(details);
+	if (!json_filenames) {
+		return -1;
+	}
+
+	json_object = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: o}",
+			"type", "fax"
+			"subtype", "status",
+			"operation", (details->caps & AST_FAX_TECH_GATEWAY) ? "gateway" : (details->caps & AST_FAX_TECH_RECEIVE) ? "receive" : "send",
+			"status", status,
+			"local_station_id", details->localstationid,
+			"filenames", json_filenames);
+	if (!json_object) {
+		return -1;
+	}
+
+	{
+		SCOPED_CHANNELLOCK(lock, chan);
+
+		message = ast_channel_cached_blob_create(chan, json_object);
+		if (!message) {
+			return -1;
+		}
+		stasis_publish(ast_channel_topic(chan), message);
+	}
 	return 0;
 }
 
@@ -1738,13 +1760,54 @@
 	return 0;
 }
 
+/*! \brief Report on the final state of a receive fax operation
+ * \note This will lock the \ref ast_channel
+ */
+static int report_receive_fax_status(struct ast_channel *chan, const char *filename)
+{
+	RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, json_array, ast_json_array_create(), ast_json_unref);
+	struct ast_json *json_filename = ast_json_string_create(filename);
+
+	if (!json_array || !json_filename) {
+		return -1;
+	}
+	ast_json_array_append(json_array, json_filename);
+
+	{
+		SCOPED_CHANNELLOCK(lock, chan);
+
+		json_object = ast_json_pack("s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: o",
+				"type", "fax"
+				"subtype", "receive",
+				"remote_station_id", S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
+				"local_station_id", S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
+				"fax_pages", S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
+				"fax_resolution", S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
+				"fax_bitrate", S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
+				"filenames", json_array);
+		if (!json_object) {
+			return -1;
+		}
+
+		message = ast_channel_cached_blob_create(chan, json_object);
+		if (!message) {
+			return -1;
+		}
+
+		stasis_publish(ast_channel_topic(chan), message);
+	}
+	return 0;
+}
+
 /*! \brief initiate a receive FAX session */
 static int receivefax_exec(struct ast_channel *chan, const char *data)
 {
 	char *parse, modems[128] = "";
 	int channel_alive;
-	struct ast_fax_session_details *details;
-	struct ast_fax_session *s;
+	RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_fax_session *, s, NULL, ao2_cleanup);
 	struct ast_fax_tech_token *token = NULL;
 	struct ast_fax_document *doc;
 	AST_DECLARE_APP_ARGS(args,
@@ -1752,7 +1815,6 @@
 		AST_APP_ARG(options);
 	);
 	struct ast_flags opts = { 0, };
-	struct manager_event_info info;
 	enum ast_t38_state t38state;
 
 	/* initialize output channel variables */
@@ -1780,7 +1842,6 @@
 		ast_string_field_set(details, resultstr, "can't receive a fax on a channel with a T.38 gateway");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "executing ReceiveFAX on a channel with a T.38 Gateway is not supported\n");
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1789,7 +1850,6 @@
 		ast_string_field_set(details, resultstr, "maxrate is less than minrate");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1799,7 +1859,6 @@
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
 		set_channel_variables(chan, details);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1809,7 +1868,6 @@
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
 		set_channel_variables(chan, details);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1818,7 +1876,6 @@
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
-		ao2_ref(details, -1);
 		return -1;
 	}
 	parse = ast_strdupa(data);
@@ -1829,7 +1886,6 @@
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
-		ao2_ref(details, -1);
 		return -1;
 	}
 	if (ast_strlen_zero(args.filename)) {
@@ -1837,7 +1893,6 @@
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[,options])\n", app_receivefax);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1847,7 +1902,6 @@
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s does not support polling\n", app_receivefax);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1861,7 +1915,6 @@
 		ast_string_field_set(details, resultstr, "error allocating memory");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1894,7 +1947,6 @@
 		ast_string_field_set(details, resultstr, "error reserving fax session");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -1905,8 +1957,6 @@
 			set_channel_variables(chan, details);
 			ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
 			fax_session_release(s, token);
-			ao2_ref(s, -1);
-			ao2_ref(details, -1);
 			return -1;
 		}
 	}
@@ -1917,8 +1967,6 @@
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
 			set_channel_variables(chan, details);
 			fax_session_release(s, token);
-			ao2_ref(s, -1);
-			ao2_ref(details, -1);
 			return -1;
 		}
 	} else {
@@ -1931,8 +1979,6 @@
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
 			set_channel_variables(chan, details);
 			fax_session_release(s, token);
-			ao2_ref(s, -1);
-			ao2_ref(details, -1);
 			ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
 			return -1;
 		}
@@ -1948,36 +1994,9 @@
 		}
 	}
 
-	/* send out the AMI completion event */
-	ast_channel_lock(chan);
-
-	get_manager_event_info(chan, &info);
-	manager_event(EVENT_FLAG_CALL,
-		      "ReceiveFAX",
-		      "Channel: %s\r\n"
-		      "Context: %s\r\n"
-		      "Exten: %s\r\n"
-		      "CallerID: %s\r\n"
-		      "RemoteStationID: %s\r\n"
-		      "LocalStationID: %s\r\n"
-		      "PagesTransferred: %s\r\n"
-		      "Resolution: %s\r\n"
-		      "TransferRate: %s\r\n"
-		      "FileName: %s\r\n",
-		      ast_channel_name(chan),
-		      info.context,
-		      info.exten,
-		      info.cid,
-		      S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
-		      args.filename);
-	ast_channel_unlock(chan);
-
-	ao2_ref(s, -1);
-	ao2_ref(details, -1);
+	if (report_receive_fax_status(chan, args.filename)) {
+		ast_log(AST_LOG_ERROR, "Error publishing ReceiveFax status message\n");
+	}
 
 	/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
 	return (!channel_alive) ? -1 : 0;
@@ -2223,14 +2242,54 @@
 	return 0;
 }
 
+/*!
+ * \brief Report on the status of a completed fax send attempt
+ * \note This will lock the \ref ast_channel
+ */
+static int report_send_fax_status(struct ast_channel *chan, struct ast_fax_session_details *details)
+{
+	RAII_VAR(struct ast_json *, json_obj, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	struct ast_json *json_filenames;
+
+	json_filenames = generate_filenames_json(details);
+	if (!json_filenames) {
+		return -1;
+	}
+
+	{
+		SCOPED_CHANNELLOCK(lock, chan);
+		json_obj = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: o}",
+				"type", "fax"
+				"subtype", "send",
+				"remote_station_id", S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
+				"local_station_id", S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
+				"fax_pages", S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
+				"fax_resolution", S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
+				"fax_bitrate", S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
+				"filenames", json_filenames);
+		if (!json_obj) {
+			return -1;
+		}
+
+		message = ast_channel_cached_blob_create(chan, json_obj);
+		if (!message) {
+			return -1;
+		}
+		stasis_publish(ast_channel_topic(chan), message);
+	}
+	return 0;
+}
+
+
 
 /*! \brief initiate a send FAX session */
 static int sendfax_exec(struct ast_channel *chan, const char *data)
 {
 	char *parse, *filenames, *c, modems[128] = "";
 	int channel_alive, file_count;
-	struct ast_fax_session_details *details;
-	struct ast_fax_session *s;
+	RAII_VAR(struct ast_fax_session_details *, details, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_fax_session *, s, NULL, ao2_cleanup);
 	struct ast_fax_tech_token *token = NULL;
 	struct ast_fax_document *doc;
 	AST_DECLARE_APP_ARGS(args,
@@ -2238,7 +2297,6 @@
 		AST_APP_ARG(options);
 	);
 	struct ast_flags opts = { 0, };
-	struct manager_event_info info;
 	enum ast_t38_state t38state;
 
 	/* initialize output channel variables */
@@ -2266,7 +2324,6 @@
 		ast_string_field_set(details, resultstr, "can't send a fax on a channel with a T.38 gateway");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "executing SendFAX on a channel with a T.38 Gateway is not supported\n");
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2275,7 +2332,6 @@
 		ast_string_field_set(details, resultstr, "maxrate is less than minrate");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "maxrate %d is less than minrate %d\n", details->maxrate, details->minrate);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2285,7 +2341,6 @@
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "incompatible 'modems' and 'minrate' settings");
 		set_channel_variables(chan, details);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2295,7 +2350,6 @@
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "incompatible 'modems' and 'maxrate' settings");
 		set_channel_variables(chan, details);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2304,7 +2358,6 @@
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]][,options])\n", app_sendfax);
-		ao2_ref(details, -1);
 		return -1;
 	}
 	parse = ast_strdupa(data);
@@ -2316,7 +2369,6 @@
 		ast_string_field_set(details, error, "INVALID_ARGUMENTS");
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
-		ao2_ref(details, -1);
 		return -1;
 	}
 	if (ast_strlen_zero(args.filenames)) {
@@ -2324,7 +2376,6 @@
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s requires an argument (filename[&filename[&filename]],options])\n", app_sendfax);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2334,7 +2385,6 @@
 		ast_string_field_set(details, resultstr, "invalid arguments");
 		set_channel_variables(chan, details);
 		ast_log(LOG_WARNING, "%s does not support polling\n", app_sendfax);
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2348,7 +2398,6 @@
 			ast_string_field_set(details, resultstr, "error reading file");
 			set_channel_variables(chan, details);
 			ast_log(LOG_ERROR, "access failure.  Verify '%s' exists and check permissions.\n", args.filenames);
-			ao2_ref(details, -1);
 			return -1;
 		}
 
@@ -2357,7 +2406,6 @@
 			ast_string_field_set(details, resultstr, "error allocating memory");
 			set_channel_variables(chan, details);
 			ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
-			ao2_ref(details, -1);
 			return -1;
 		}
 
@@ -2402,7 +2450,6 @@
 		ast_string_field_set(details, resultstr, "error reserving fax session");
 		set_channel_variables(chan, details);
 		ast_log(LOG_ERROR, "Unable to reserve FAX session.\n");
-		ao2_ref(details, -1);
 		return -1;
 	}
 
@@ -2413,8 +2460,6 @@
 			set_channel_variables(chan, details);
 			ast_log(LOG_WARNING, "Channel '%s' failed answer attempt.\n", ast_channel_name(chan));
 			fax_session_release(s, token);
-			ao2_ref(s, -1);
-			ao2_ref(details, -1);
 			return -1;
 		}
 	}
@@ -2425,8 +2470,6 @@
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
 			set_channel_variables(chan, details);
 			fax_session_release(s, token);
-			ao2_ref(s, -1);
-			ao2_ref(details, -1);
 			return -1;
 		}
 	} else {
@@ -2439,8 +2482,6 @@
 			ast_string_field_set(details, resultstr, "error negotiating T.38");
 			set_channel_variables(chan, details);
 			fax_session_release(s, token);
-			ao2_ref(s, -1);
-			ao2_ref(details, -1);
 			ast_log(LOG_ERROR, "error initializing channel '%s' in T.38 mode\n", ast_channel_name(chan));
 			return -1;
 		}
@@ -2460,42 +2501,13 @@
 
 	if (!(filenames = generate_filenames_string(details, "FileName: ", "\r\n"))) {
 		ast_log(LOG_ERROR, "Error generating SendFAX manager event\n");
-		ao2_ref(s, -1);
-		ao2_ref(details, -1);
 		return (!channel_alive) ? -1 : 0;
 	}
 
 	/* send out the AMI completion event */
-	ast_channel_lock(chan);
-	get_manager_event_info(chan, &info);
-	manager_event(EVENT_FLAG_CALL,
-		      "SendFAX",
-		      "Channel: %s\r\n"
-		      "Context: %s\r\n"
-		      "Exten: %s\r\n"
-		      "CallerID: %s\r\n"
-		      "RemoteStationID: %s\r\n"
-		      "LocalStationID: %s\r\n"
-		      "PagesTransferred: %s\r\n"
-		      "Resolution: %s\r\n"
-		      "TransferRate: %s\r\n"
-		      "%s\r\n",
-		      ast_channel_name(chan),
-		      info.context,
-		      info.exten,
-		      info.cid,
-		      S_OR(pbx_builtin_getvar_helper(chan, "REMOTESTATIONID"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "FAXPAGES"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "FAXRESOLUTION"), ""),
-		      S_OR(pbx_builtin_getvar_helper(chan, "FAXBITRATE"), ""),
-		      filenames);
-	ast_channel_unlock(chan);
-
-	ast_free(filenames);
-
-	ao2_ref(s, -1);
-	ao2_ref(details, -1);
+	if (report_send_fax_status(chan, details)) {
+		ast_log(AST_LOG_ERROR, "Error publishing SendFAX status message\n");
+	}
 
 	/* If the channel hungup return -1; otherwise, return 0 to continue in the dialplan */
 	return (!channel_alive) ? -1 : 0;




More information about the asterisk-commits mailing list