[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