[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