[asterisk-commits] mnicholson: branch irroot/t38gateway-trunk r323841 - in /team/irroot/t38gatew...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jun 15 14:06:05 CDT 2011
Author: mnicholson
Date: Wed Jun 15 14:05:58 2011
New Revision: 323841
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=323841
Log:
code cleanup of the gateway framehook attach and detach code
Modified:
team/irroot/t38gateway-trunk/include/asterisk/res_fax.h
team/irroot/t38gateway-trunk/res/res_fax.c
Modified: team/irroot/t38gateway-trunk/include/asterisk/res_fax.h
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/include/asterisk/res_fax.h?view=diff&rev=323841&r1=323840&r2=323841
==============================================================================
--- team/irroot/t38gateway-trunk/include/asterisk/res_fax.h (original)
+++ team/irroot/t38gateway-trunk/include/asterisk/res_fax.h Wed Jun 15 14:05:58 2011
@@ -172,6 +172,8 @@
struct ast_fax_t38_parameters our_t38_parameters;
/*! the other endpoint's T.38 session parameters, if any */
struct ast_fax_t38_parameters their_t38_parameters;
+ /*! the id of the t.38 gateway framehook for this channel */
+ int gateway_id;
};
struct ast_fax_tech;
@@ -210,24 +212,6 @@
/* if this overlaps with any AST_FRFLAG_* values, problems will occur */
#define AST_FAX_FRFLAG_GATEWAY (1 << 13)
-
-/*! \brief used for gateway framehook */
-struct ast_fax_session_gateway {
- /*! FAX Session*/
- struct ast_fax_session *s;
- /*! DSP Processor*/
- struct ast_dsp *chan_dsp;
- struct ast_dsp *peer_dsp;
- /*! framehook used in gateway mode */
- int framehook;
- /*! bridged*/
- int bridged;
- /*Original audio formats*/
- struct ast_format chan_read_format;
- struct ast_format chan_write_format;
- struct ast_format peer_read_format;
- struct ast_format peer_write_format;
-};
/*! \brief used to register a FAX technology module with res_fax */
struct ast_fax_tech {
Modified: team/irroot/t38gateway-trunk/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-trunk/res/res_fax.c?view=diff&rev=323841&r1=323840&r2=323841
==============================================================================
--- team/irroot/t38gateway-trunk/res/res_fax.c (original)
+++ team/irroot/t38gateway-trunk/res/res_fax.c Wed Jun 15 14:05:58 2011
@@ -250,6 +250,24 @@
struct ast_dsp *dsp;
};
+/*! \brief used for gateway framehook */
+struct fax_gateway {
+ /*! FAX Session*/
+ struct ast_fax_session *s;
+ /*! DSP Processor*/
+ struct ast_dsp *chan_dsp;
+ struct ast_dsp *peer_dsp;
+ /*! framehook used in gateway mode */
+ int framehook;
+ /*! bridged*/
+ int bridged;
+ /*Original audio formats*/
+ struct ast_format chan_read_format;
+ struct ast_format chan_write_format;
+ struct ast_format peer_read_format;
+ struct ast_format peer_write_format;
+};
+
static int fax_logger_level = -1;
/*! \brief maximum buckets for res_fax ao2 containers */
@@ -429,10 +447,11 @@
d->option.send_ced = AST_FAX_OPTFLAG_FALSE;
d->option.ecm = general_options.ecm;
d->option.statusevents = general_options.statusevents;
+ d->option.t38gateway = AST_FAX_OPTFLAG_FALSE;
d->modems = general_options.modems;
d->minrate = general_options.minrate;
d->maxrate = general_options.maxrate;
- d->option.t38gateway = AST_FAX_OPTFLAG_FALSE;
+ d->gateway_id = -1;
return d;
}
@@ -2273,56 +2292,53 @@
return (!channel_alive) ? -1 : 0;
}
-/*! \brief channel datastore holding a T38 fax gateway object*/
-static const struct ast_datastore_info fax_datastore_gateway = {
- .type = "res_fax_gateway",
- .destroy = destroy_callback,
-};
+/*! \brief destroy a FAX gateway session structure */
+static void destroy_gateway(void *data)
+{
+ struct fax_gateway *gateway = data;
+
+ if (gateway->chan_dsp) {
+ ast_dsp_free(gateway->chan_dsp);
+ gateway->chan_dsp = NULL;
+ }
+
+ if (gateway->peer_dsp) {
+ ast_dsp_free(gateway->peer_dsp);
+ gateway->peer_dsp = NULL;
+ }
+}
/*! \brief returns a reference counted gateway structure from the channel's fax gateway datastore.
* \param chan channel to look for the datastore
* \param create flag if set the datastore will be created if not found
* \return fax gateway object or null if it does not exist or cant be created depending on create.*/
-static struct ast_fax_session_gateway *find_session_gateway(struct ast_channel *chan, int create)
-{
- struct ast_fax_session_gateway *gateway;
- struct ast_datastore *datastore;
-
- ast_channel_lock(chan);
- datastore = ast_channel_datastore_find(chan, &fax_datastore_gateway, NULL);
- ast_channel_unlock(chan);
- if (create && ((!datastore || !datastore->data))) {
- gateway = ao2_alloc(sizeof(*gateway), NULL);
- if (!gateway) {
- return NULL;
- }
-
- if (!(datastore = ast_datastore_alloc(&fax_datastore_gateway, NULL))) {
- ast_log(LOG_WARNING, "channel '%s' can't get a datastore!\n", chan->name);
- ao2_ref(gateway, -1);
- return NULL;
- }
-
- /* add the datastore to the channel*/
- datastore->data = gateway;
-
- gateway->framehook = -1;
- gateway->chan_dsp = NULL;
- gateway->peer_dsp = NULL;
- gateway->s = NULL;
- gateway->bridged = 0;
-
- ast_channel_lock(chan);
- ast_channel_datastore_add(chan, datastore);
- ast_channel_unlock(chan);
- } else if (datastore && datastore->data) {
- gateway = datastore->data;
- } else {
+static struct fax_gateway *fax_gateway_new(void)
+{
+ struct fax_gateway *gateway = ao2_alloc(sizeof(*gateway), destroy_gateway);
+ if (!gateway) {
return NULL;
}
- /* i need a ref here for create and find as the datastore must hold one */
- ao2_ref(gateway, 1);
+ gateway->chan_dsp = ast_dsp_new();
+ if (!gateway->chan_dsp) {
+ ao2_ref(gateway, -1);
+ return NULL;
+ }
+
+ gateway->peer_dsp = ast_dsp_new();
+ if (!gateway->peer_dsp) {
+ ao2_ref(gateway, -1);
+ return NULL;
+ }
+
+ gateway->framehook = -1;
+
+ ast_dsp_set_features(gateway->chan_dsp, DSP_FEATURE_FAX_DETECT);
+ ast_dsp_set_faxmode(gateway->chan_dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
+
+ ast_dsp_set_features(gateway->peer_dsp, DSP_FEATURE_FAX_DETECT);
+ ast_dsp_set_faxmode(gateway->peer_dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
+
return gateway;
}
@@ -2330,17 +2346,9 @@
* \param details fax session details
* \param chan active channel
* \return 0 on error 1 on success*/
-static int ast_t38_gateway(struct ast_fax_session_details *details, struct ast_channel *chan)
-{
- struct ast_fax_session_gateway *gateway;
-
- gateway = find_session_gateway(chan, 0);
- if (!gateway) {
- return 0;
- }
-
+static int ast_t38_gateway(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
+{
if (gateway->s) {
- ao2_ref(gateway, -1);
return 0;
}
@@ -2349,20 +2357,17 @@
if (!(gateway->s = fax_session_new(details, chan, NULL, NULL))) {
ast_log(LOG_ERROR, "Can't create a FAX session, FAX attempt failed.\n");
report_fax_status(chan, details, "No Available Resource");
- ao2_ref(gateway, -1);
return 0;
}
if (gateway->s->tech->start_session(gateway->s) < 0) {
ao2_ref(gateway->s, -1);
gateway->s = NULL;
- ao2_ref(gateway, -1);
return 0;
}
/* looks like we good to go */
gateway->s->state = AST_FAX_STATE_ACTIVE;
- ao2_ref(gateway, -1);
return 1;
}
@@ -2372,7 +2377,7 @@
* \param active channel the frame originated on
* \param f the control frame to process
* \return processed control frame or null frame*/
-static struct ast_frame *ast_t38_gateway_parameters(struct ast_channel *chan,struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
+static struct ast_frame *ast_t38_gateway_parameters(struct fax_gateway *gateway, struct ast_channel *chan,struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
{
struct ast_control_t38_parameters *active_param;
struct ast_fax_t38_parameters *t38_param;
@@ -2439,7 +2444,7 @@
/* Start gateway if both channels are in a stable T.38 (not negotiating) state and only one of them is not negotiated! */
if (((activestate == T38_STATE_NEGOTIATED) && ((inactivestate == T38_STATE_UNAVAILABLE) || (inactivestate == T38_STATE_REJECTED))) ||
((inactivestate == T38_STATE_NEGOTIATED) && ((activestate == T38_STATE_UNAVAILABLE) || (activestate == T38_STATE_REJECTED)))) {
- if (ast_t38_gateway(details, chan)) {
+ if (ast_t38_gateway(gateway, details, chan)) {
ast_verb(3, "T.38 Gateway starting for chan %s and peer %s\n", chan->name, peer->name);
}
}
@@ -2451,21 +2456,11 @@
/*! \brief Destroy the gateway data structure when the framehook is detached
* \param data framehook data (gateway data)*/
static void t38_gw_fh_destroy(void *data) {
- struct ast_fax_session_gateway *gateway = data;
- struct ast_fax_session *s;
+ struct fax_gateway *gateway = data;
+ struct ast_fax_session *s;
if (!gateway) {
return;
- }
-
- if (gateway->chan_dsp) {
- ast_dsp_free(gateway->chan_dsp);
- gateway->chan_dsp = NULL;
- }
-
- if (gateway->peer_dsp) {
- ast_dsp_free(gateway->peer_dsp);
- gateway->peer_dsp = NULL;
}
if (gateway->s) {
@@ -2494,54 +2489,57 @@
struct ast_control_t38_parameters *t38_parameters;
enum ast_t38_state t38state;
enum ast_t38_state t38pstate;
- struct ast_fax_session_gateway *gateway = data;
+ struct fax_gateway *gateway = data;
struct ast_fax_session *s;
struct ast_frame *dfr = NULL;
struct ast_channel *peer, *active, *inactive;
struct ast_dsp *dsp;
- if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED) || (event == AST_FRAMEHOOK_EVENT_DETACHED)) {
+ /* restore audio formats when we are detached */
+ if (event == AST_FRAMEHOOK_EVENT_DETACHED && gateway->bridged) {
+ ast_set_read_format(chan, &gateway->chan_read_format);
+ ast_set_read_format(chan, &gateway->chan_write_format);
+ peer = ast_bridged_channel(chan);
+ if (peer) {
+ ast_set_read_format(peer, &gateway->peer_read_format);
+ ast_set_read_format(peer, &gateway->peer_write_format);
+ ast_channel_make_compatible(chan, peer);
+ }
+
+ return NULL;
+ }
+
+ if (!f || (event == AST_FRAMEHOOK_EVENT_ATTACHED)) {
return NULL;
};
-
- if (!gateway) {
- return f;
- }
/* this frame was generated by the fax gateway, pass it on */
if (ast_test_flag(f, AST_FAX_FRFLAG_GATEWAY)) {
return f;
}
+ s = gateway->s;
+
+ /* when we become active change the formats to SLIN for CED detect and T.30 */
peer = ast_bridged_channel(chan);
- s = gateway->s;
-
- switch (event) {
- case AST_FRAMEHOOK_EVENT_WRITE:
- /* when we become active change the formats to SLIN for CED detect and T.30*/
- if (peer && !gateway->bridged) {
- ast_format_copy(&gateway->chan_read_format, &chan->readformat);
- ast_format_copy(&gateway->chan_write_format, &chan->readformat);
- ast_format_copy(&gateway->peer_read_format, &peer->readformat);
- ast_format_copy(&gateway->peer_write_format, &peer->readformat);
- ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
- ast_set_read_format_by_id(peer, AST_FORMAT_SLINEAR);
- ast_set_write_format_by_id(peer, AST_FORMAT_SLINEAR);
- ast_channel_make_compatible(chan, peer);
- gateway->bridged = 1;
- }
- active = peer;
- break;
- case AST_FRAMEHOOK_EVENT_READ:
- active = chan;
- break;
- default:
- ast_log(LOG_WARNING, "Unhandled Framehook Event %i\n",event);
- return f;
- }
-
- /* filter frames*/
+ if (!gateway->bridged && peer) {
+ ast_format_copy(&gateway->chan_read_format, &chan->readformat);
+ ast_format_copy(&gateway->chan_write_format, &chan->readformat);
+
+ ast_format_copy(&gateway->peer_read_format, &peer->readformat);
+ ast_format_copy(&gateway->peer_write_format, &peer->readformat);
+
+ ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
+ ast_set_write_format_by_id(chan, AST_FORMAT_SLINEAR);
+
+ ast_set_read_format_by_id(peer, AST_FORMAT_SLINEAR);
+ ast_set_write_format_by_id(peer, AST_FORMAT_SLINEAR);
+
+ ast_channel_make_compatible(chan, peer);
+ gateway->bridged = 1;
+ }
+
+ /* only handle VOICE, MODEM, and CONTROL frames*/
switch (f->frametype) {
case AST_FRAME_VOICE:
switch (f->subclass.format.id) {
@@ -2564,6 +2562,19 @@
return f;
}
+ /* detect the active channel */
+ switch (event) {
+ case AST_FRAMEHOOK_EVENT_WRITE:
+ active = peer;
+ break;
+ case AST_FRAMEHOOK_EVENT_READ:
+ active = chan;
+ break;
+ default:
+ ast_log(LOG_WARNING, "Unhandled Framehook Event %i\n",event);
+ return f;
+ }
+
/*handle control frames*/
if (f->frametype == AST_FRAME_CONTROL) {
switch (f->subclass.integer) {
@@ -2577,7 +2588,7 @@
if (!peer) {
return f;
}
- f = ast_t38_gateway_parameters(chan,peer,active,f);
+ f = ast_t38_gateway_parameters(gateway, chan,peer,active,f);
default:
return f;
}
@@ -2661,12 +2672,12 @@
return f;
}
-/*! \brief attach a gateway framehook object to the channel
- * \details create and setup the gateway framehook and datastore
- * \param chan channel im attached too*/
-static void gateway_attach_hook(struct ast_channel *chan)
-{
- struct ast_fax_session_gateway *gateway;
+/*! \brief Attach a gateway framehook object to a channel.
+ * \param chan the channel to attach to
+ */
+static int gateway_attach_hook(struct ast_channel *chan)
+{
+ struct fax_gateway *gateway;
struct ast_framehook_interface fr_hook = {
.version = AST_FRAMEHOOK_INTERFACE_VERSION,
.event_cb = t38_gw_framehook,
@@ -2674,63 +2685,22 @@
};
/* set up the frame hook*/
- gateway = find_session_gateway(chan, 1);
- if (gateway && (gateway->framehook < 0)) {
- fr_hook.data = gateway;
- ast_channel_lock(chan);
- gateway->framehook = ast_framehook_attach(chan, &fr_hook);
- ast_channel_unlock(chan);
- if (gateway->framehook >= 0) {
- gateway->chan_dsp = ast_dsp_new();
- if (gateway->chan_dsp) {
- ast_dsp_set_features(gateway->chan_dsp, DSP_FEATURE_FAX_DETECT);
- ast_dsp_set_faxmode(gateway->chan_dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
- }
- gateway->peer_dsp = ast_dsp_new();
- if (gateway->peer_dsp) {
- ast_dsp_set_features(gateway->peer_dsp, DSP_FEATURE_FAX_DETECT);
- ast_dsp_set_faxmode(gateway->peer_dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_CED);
- }
- } else {
- /* im not in a frame hook*/
- ao2_ref(gateway, -1);
- }
- } else if (gateway) {
+ gateway = fax_gateway_new();
+ if (!gateway) {
+ return -1;
+ }
+
+ fr_hook.data = gateway;
+ ast_channel_lock(chan);
+ gateway->framehook = ast_framehook_attach(chan, &fr_hook);
+ ast_channel_unlock(chan);
+
+ if (gateway->framehook < 0) {
ao2_ref(gateway, -1);
- }
-}
-
-/*! \brief detach a gateway framehook object to the channel
- * \details remove and destroy the gateway framehook and datastore
- * \param chan channel im attached too*/
-static void gateway_remove_hook(struct ast_channel *chan)
-{
- struct ast_fax_session_gateway *gateway;
- struct ast_datastore *datastore;
- struct ast_channel *peer;
-
- ast_channel_lock(chan);
- datastore = ast_channel_datastore_find(chan, &fax_datastore_gateway, NULL);
- if (datastore) {
- ast_channel_datastore_remove(chan, datastore);
- if (datastore->data) {
- gateway = datastore->data;
- ast_datastore_free(datastore);
- /* restore audio formats*/
- if (gateway->bridged) {
- ast_set_read_format(chan, &gateway->chan_read_format);
- ast_set_read_format(chan, &gateway->chan_write_format);
- peer = ast_bridged_channel(chan);
- if (peer) {
- ast_set_read_format(peer, &gateway->peer_read_format);
- ast_set_read_format(peer, &gateway->peer_write_format);
- ast_channel_make_compatible(chan, peer);
- }
- }
- ast_framehook_detach(chan, gateway->framehook);
- }
- }
- ast_channel_unlock(chan);
+ return -1;
+ }
+
+ return gateway->framehook;
}
/*! \brief Alternate wait app that listens for CNG
@@ -3315,13 +3285,23 @@
!strcasecmp(data, "t38_gateway") || !strcasecmp(data, "faxgateway")) {
const char *val = ast_skip_blanks(value);
if (ast_true(val)) {
- gateway_attach_hook(chan);
- details->option.t38gateway = AST_FAX_OPTFLAG_TRUE;
+ if (details->gateway_id < 0) {
+ details->gateway_id = gateway_attach_hook(chan);
+ if (details->gateway_id < 0) {
+ ast_log(LOG_ERROR, "Error attaching T.38 gateway to channel %s.\n", chan->name);
+ res = -1;
+ } else {
+ details->option.t38gateway = AST_FAX_OPTFLAG_TRUE;
+ }
+ } else {
+ ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", chan->name);
+ }
} else if (ast_false(val)) {
- gateway_remove_hook(chan);
+ ast_framehook_detach(chan, details->gateway_id);
+ details->gateway_id = -1;
details->option.t38gateway = AST_FAX_OPTFLAG_FALSE;
} else {
- ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(t38gateway).\n", value);
+ ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
}
} else if (!strcasecmp(data, "headerinfo")) {
ast_string_field_set(details, headerinfo, value);
More information about the asterisk-commits
mailing list