[asterisk-commits] mmichelson: branch mmichelson/transfer_stasis r391405 - in /team/mmichelson/t...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jun 11 11:11:57 CDT 2013


Author: mmichelson
Date: Tue Jun 11 11:11:55 2013
New Revision: 391405

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=391405
Log:
Resolve conflicts and reset automerge.


Added:
    team/mmichelson/transfer_stasis/res/res_stasis_bridge_add.c
      - copied unchanged from r391403, trunk/res/res_stasis_bridge_add.c
    team/mmichelson/transfer_stasis/res/res_stasis_bridge_add.exports.in
      - copied unchanged from r391403, trunk/res/res_stasis_bridge_add.exports.in
Modified:
    team/mmichelson/transfer_stasis/   (props changed)
    team/mmichelson/transfer_stasis/UPGRADE.txt
    team/mmichelson/transfer_stasis/apps/app_queue.c
    team/mmichelson/transfer_stasis/channels/chan_iax2.c
    team/mmichelson/transfer_stasis/channels/chan_skinny.c
    team/mmichelson/transfer_stasis/channels/chan_unistim.c
    team/mmichelson/transfer_stasis/configs/queues.conf.sample
    team/mmichelson/transfer_stasis/include/asterisk/stasis.h
    team/mmichelson/transfer_stasis/include/asterisk/stasis_app.h
    team/mmichelson/transfer_stasis/include/asterisk/stasis_bridging.h
    team/mmichelson/transfer_stasis/main/features_config.c
    team/mmichelson/transfer_stasis/main/loader.c
    team/mmichelson/transfer_stasis/main/manager.c
    team/mmichelson/transfer_stasis/main/manager_channels.c
    team/mmichelson/transfer_stasis/main/parking.c
    team/mmichelson/transfer_stasis/main/stasis_bridging.c
    team/mmichelson/transfer_stasis/main/stasis_channels.c
    team/mmichelson/transfer_stasis/main/stasis_message.c
    team/mmichelson/transfer_stasis/res/res_agi.c
    team/mmichelson/transfer_stasis/res/res_stasis.c
    team/mmichelson/transfer_stasis/res/res_stasis_json_events.c
    team/mmichelson/transfer_stasis/res/res_stasis_json_events.exports.in
    team/mmichelson/transfer_stasis/res/stasis/app.c
    team/mmichelson/transfer_stasis/res/stasis/app.h
    team/mmichelson/transfer_stasis/res/stasis/control.c
    team/mmichelson/transfer_stasis/res/stasis_http/resource_bridges.c
    team/mmichelson/transfer_stasis/res/stasis_http/resource_bridges.h
    team/mmichelson/transfer_stasis/res/stasis_json/resource_events.h
    team/mmichelson/transfer_stasis/rest-api/api-docs/bridges.json
    team/mmichelson/transfer_stasis/rest-api/api-docs/events.json
    team/mmichelson/transfer_stasis/tests/test_stasis.c
    team/mmichelson/transfer_stasis/tests/test_stasis_channels.c

Propchange: team/mmichelson/transfer_stasis/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/mmichelson/transfer_stasis/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/mmichelson/transfer_stasis/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Jun 11 11:11:55 2013
@@ -1,1 +1,1 @@
-/trunk:1-391171
+/trunk:1-391404

Modified: team/mmichelson/transfer_stasis/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/UPGRADE.txt?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/UPGRADE.txt (original)
+++ team/mmichelson/transfer_stasis/UPGRADE.txt Tue Jun 11 11:11:55 2013
@@ -20,7 +20,6 @@
 === UPGRADE-11.txt -- Upgrade info for 10 to 11
 ===
 ===========================================================
-
 
 AMI:
  - The SIP SIPqualifypeer action now sends a response indicating it will qualify
@@ -55,6 +54,11 @@
    Queue member being paused would result in a disposition of BUSY.
  - Removed the queues.conf check_state_unknown option.  It is no longer
    necessary.
+ - It is now possible to play the Queue prompts to the first user waiting in a
+   call queue. Note that this may impact the ability for agents to talk with
+   users, as a prompt may still be playing when an agent connects to the user.
+   This ability is disabled by default but can be enabled on an individual
+   queue using the 'announce-to-first-user' option.
 
 Dial:
  - Now recognizes 'W' to pause sending DTMF for one second in addition to

Modified: team/mmichelson/transfer_stasis/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/apps/app_queue.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/apps/app_queue.c (original)
+++ team/mmichelson/transfer_stasis/apps/app_queue.c Tue Jun 11 11:11:55 2013
@@ -1517,6 +1517,7 @@
 	struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
 	unsigned int dead:1;
 	unsigned int ringinuse:1;
+	unsigned int announce_to_first_user:1; /*!< Whether or not we announce to the first user in a queue */
 	unsigned int setinterfacevar:1;
 	unsigned int setqueuevar:1;
 	unsigned int setqueueentryvar:1;
@@ -2370,6 +2371,7 @@
 	q->roundingseconds = 0; /* Default - don't announce seconds */
 	q->servicelevel = 0;
 	q->ringinuse = 1;
+	q->announce_to_first_user = 0;
 	q->setinterfacevar = 0;
 	q->setqueuevar = 0;
 	q->setqueueentryvar = 0;
@@ -2648,6 +2650,8 @@
 		ast_string_field_set(q, sound_reporthold, val);
 	} else if (!strcasecmp(param, "announce-frequency")) {
 		q->announcefrequency = atoi(val);
+	} else if (!strcasecmp(param, "announce-to-first-user")) {
+		q->announce_to_first_user = ast_true(val);
 	} else if (!strcasecmp(param, "min-announce-frequency")) {
 		q->minannouncefrequency = atoi(val);
 		ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
@@ -4820,12 +4824,12 @@
 	}
 
 	/* Make a position announcement, if enabled */
- 	if (qe->parent->announcefrequency) {
+ 	if (qe->parent->announcefrequency && qe->parent->announce_to_first_user) {
 		say_position(qe, ringing);
 	}
 
  	/* Make a periodic announcement, if enabled */
- 	if (qe->parent->periodicannouncefrequency) {
+ 	if (qe->parent->periodicannouncefrequency && qe->parent->announce_to_first_user) {
  		say_periodic_announcement(qe, ringing);
  	}
  
@@ -9661,6 +9665,7 @@
 	MEMBER(call_queue, sound_reporthold, AST_DATA_STRING)		\
 	MEMBER(call_queue, dead, AST_DATA_BOOLEAN)			\
 	MEMBER(call_queue, ringinuse, AST_DATA_BOOLEAN)			\
+	MEMBER(call_queue, announce_to_first_user, AST_DATA_BOOLEAN)	\
 	MEMBER(call_queue, setinterfacevar, AST_DATA_BOOLEAN)		\
 	MEMBER(call_queue, setqueuevar, AST_DATA_BOOLEAN)		\
 	MEMBER(call_queue, setqueueentryvar, AST_DATA_BOOLEAN)		\

Modified: team/mmichelson/transfer_stasis/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/channels/chan_iax2.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/channels/chan_iax2.c (original)
+++ team/mmichelson/transfer_stasis/channels/chan_iax2.c Tue Jun 11 11:11:55 2013
@@ -11204,15 +11204,28 @@
 				}
 				break;
 			case IAX_COMMAND_TXREJ:
-				iaxs[fr->callno]->transferring = 0;
+				if (iaxs[fr->callno]->bridgecallno) {
+					while (ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) {
+						DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
+					}
+					if (!iaxs[fr->callno]) {
+						break;
+					}
+				}
+
+				iaxs[fr->callno]->transferring = TRANSFER_NONE;
 				ast_verb(3, "Channel '%s' unable to transfer\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>");
 				memset(&iaxs[fr->callno]->transfer, 0, sizeof(iaxs[fr->callno]->transfer));
-				if (iaxs[fr->callno]->bridgecallno) {
-					if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
-						iaxs[iaxs[fr->callno]->bridgecallno]->transferring = 0;
-						send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
-					}
+
+				if (!iaxs[fr->callno]->bridgecallno) {
+					break;
 				}
+
+				if (iaxs[iaxs[fr->callno]->bridgecallno]->transferring) {
+					iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_NONE;
+					send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREJ, 0, NULL, 0, -1);
+				}
+				ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
 				break;
 			case IAX_COMMAND_TXREADY:
 				if (iaxs[fr->callno]->bridgecallno) {

Modified: team/mmichelson/transfer_stasis/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/channels/chan_skinny.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/channels/chan_skinny.c (original)
+++ team/mmichelson/transfer_stasis/channels/chan_skinny.c Tue Jun 11 11:11:55 2013
@@ -81,6 +81,7 @@
 #include "asterisk/event.h"
 #include "asterisk/indications.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/bridging.h"
 
 /*** DOCUMENTATION
 	<manager name="SKINNYdevices" language="en_US">
@@ -952,6 +953,7 @@
 static const uint8_t soft_key_default_offhook[] = {
 	SOFTKEY_REDIAL,
 	SOFTKEY_ENDCALL,
+	SOFTKEY_TRNSFER,
 	SOFTKEY_CFWDALL,
 	SOFTKEY_CFWDBUSY,
 	SOFTKEY_CFWDNOANSWER,
@@ -971,6 +973,7 @@
 static const uint8_t soft_key_default_dadfd[] = {
 	SOFTKEY_BKSPC,
 	SOFTKEY_ENDCALL,
+	SOFTKEY_TRNSFER,
 	SOFTKEY_FORCEDIAL,
 };
 
@@ -1375,6 +1378,7 @@
 
 #define DIALTYPE_NORMAL      1<<0
 #define DIALTYPE_CFWD        1<<1
+#define DIALTYPE_XFER        1<<2
 
 struct skinny_subchannel {
 	ast_mutex_t lock;
@@ -1656,7 +1660,6 @@
 };
 
 static int skinny_extensionstate_cb(char *context, char *id, struct ast_state_cb_info *info, void *data);
-static int skinny_transfer(struct skinny_subchannel *sub);
 
 static struct skinny_line *skinny_line_alloc(void)
 {
@@ -5008,14 +5011,6 @@
 	int res = 0;
 	struct skinny_subchannel *sub = ast_channel_tech_pvt(ast);
 
-	if (sub->blindxfer) {
-		SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_answer(%s) on %s@%s-%d with BlindXFER, transferring\n",
-			ast_channel_name(ast), sub->line->name, sub->line->device->name, sub->callid);
-		ast_setstate(ast, AST_STATE_UP);
-		skinny_transfer(sub);
-		return 0;
-	}
-
 	sub->cxmode = SKINNY_CX_SENDRECV;
 
 	SKINNY_DEBUG(DEBUG_SUB, 3, "skinny_answer(%s) on %s@%s-%d\n",
@@ -5242,64 +5237,52 @@
 	}
 }
 
-static int skinny_transfer(struct skinny_subchannel *sub)
-{
-	struct skinny_subchannel *xferor; /* the sub doing the transferring */
-	struct skinny_subchannel *xferee; /* the sub being transferred */
-	struct ast_tone_zone_sound *ts = NULL;
-
-	if (ast_bridged_channel(sub->owner) || ast_bridged_channel(sub->related->owner)) {
-		if (sub->xferor) {
-			xferor = sub;
-			xferee = sub->related;
-		} else {
-			xferor = sub;
-			xferee = sub->related;
-		}
-
-		SKINNY_DEBUG(DEBUG_SUB, 3, "Transferee channels (local/remote): %s and %s\n",
-			ast_channel_name(xferee->owner), ast_bridged_channel(xferee->owner) ? ast_channel_name(ast_bridged_channel(xferee->owner)) : "");
-		SKINNY_DEBUG(DEBUG_SUB, 3, "Transferor channels (local/remote): %s and %s\n",
-			ast_channel_name(xferor->owner), ast_bridged_channel(xferor->owner) ? ast_channel_name(ast_bridged_channel(xferor->owner)) : "");
-
-		if (ast_bridged_channel(xferor->owner)) {
-			ast_queue_unhold(xferee->owner);
-			if (ast_channel_state(xferor->owner) == AST_STATE_RING) {
-				/* play ringing inband */
-				if ((ts = ast_get_indication_tone(ast_channel_zone(xferor->owner), "ring"))) {
-					ast_playtones_start(xferor->owner, 0, ts->data, 1);
-					ts = ast_tone_zone_sound_unref(ts);
-				}
-			}
-			SKINNY_DEBUG(DEBUG_SUB, 3, "Transfer Masquerading %s to %s\n",
-				ast_channel_name(xferee->owner), ast_bridged_channel(xferor->owner) ? ast_channel_name(ast_bridged_channel(xferor->owner)) : "");
-			if (ast_channel_masquerade(xferee->owner, ast_bridged_channel(xferor->owner))) {
-				ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-					ast_channel_name(ast_bridged_channel(xferor->owner)), ast_channel_name(xferee->owner));
-				return -1;
-			}
-		} else if (ast_bridged_channel(xferee->owner)) {
-			ast_queue_unhold(xferee->owner);
-			if (ast_channel_state(xferor->owner) == AST_STATE_RING) {
-				/* play ringing inband */
-				if ((ts = ast_get_indication_tone(ast_channel_zone(xferor->owner), "ring"))) {
-					ast_playtones_start(xferor->owner, 0, ts->data, 1);
-					ts = ast_tone_zone_sound_unref(ts);
-				}
-			}
-			SKINNY_DEBUG(DEBUG_SUB, 3, "Transfer Masquerading %s to %s\n",
-				ast_channel_name(xferor->owner), ast_bridged_channel(xferee->owner) ? ast_channel_name(ast_bridged_channel(xferee->owner)) : "");
-			if (ast_channel_masquerade(xferor->owner, ast_bridged_channel(xferee->owner))) {
-				ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
-					ast_channel_name(ast_bridged_channel(xferee->owner)), ast_channel_name(xferor->owner));
-				return -1;
-			}
-		} else {
-			ast_debug(1, "Neither %s nor %s are in a bridge, nothing to transfer\n",
-				ast_channel_name(xferor->owner), ast_channel_name(xferee->owner));
-		}
-	}
-	return 0;
+static void skinny_transfer_attended(struct skinny_subchannel *sub)
+{
+	struct skinny_subchannel *xferee;
+	struct skinny_subchannel *xferor;
+	enum ast_transfer_result res;
+
+	if (sub->xferor) {
+		xferor = sub;
+		xferee = sub->related;
+	} else {
+		xferor = sub;
+		xferee = sub->related;
+	}
+
+	ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
+	if (ast_channel_state(xferor->owner) == AST_STATE_RINGING) {
+		ast_queue_control(xferee->owner, AST_CONTROL_RINGING);
+	}
+	res = ast_bridge_transfer_attended(xferee->owner, xferor->owner);
+
+	if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
+		SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d failed to transfer %d to '%s'@'%s' - %d\n",
+			xferor->callid, xferee->callid, xferor->exten, xferor->line->context, res);
+		send_displayprinotify(xferor->line->device, "Transfer failed", NULL, 10, 5);
+		ast_queue_control(xferee->owner, AST_CONTROL_HOLD);
+	}
+}
+
+static void skinny_transfer_blind(struct skinny_subchannel *sub)
+{
+	struct skinny_subchannel *xferee = sub->related;
+	enum ast_transfer_result res;
+
+	sub->related = NULL;
+	xferee->related = NULL;
+
+	ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
+	res = ast_bridge_transfer_blind(xferee->owner, sub->exten, sub->line->context, NULL, NULL);
+
+	if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
+		SKINNY_DEBUG(DEBUG_SUB, 3, "Sub %d failed to blind transfer %d to '%s'@'%s' - %d\n",
+			sub->callid, xferee->callid, sub->exten, sub->line->context, res);
+		send_displayprinotify(sub->line->device, "Transfer failed", NULL, 10, 5);
+		ast_queue_control(xferee->owner, AST_CONTROL_HOLD);
+	}
+	dumpsub(sub, 1);
 }
 
 static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
@@ -5318,12 +5301,6 @@
 		control2str(ind), ast_channel_name(ast), sub->callid);
 	switch(ind) {
 	case AST_CONTROL_RINGING:
-		if (sub->blindxfer) {
-			SKINNY_DEBUG(DEBUG_SUB, 3, "Channel %s (Sub %d) set up for Blind Xfer, so Xfer rather than ring device\n",
-				ast_channel_name(ast), sub->callid);
-			skinny_transfer(sub);
-			break;
-		}
 		setsubstate(sub, SUBSTATE_RINGOUT);
 		return (d->earlyrtp ? -1 : 0); /* Tell asterisk to provide inband signalling if rtp started */
 	case AST_CONTROL_BUSY:
@@ -6059,6 +6036,9 @@
 		dumpsub(sub, 1);
 		transmit_cfwdstate(d, l);
 		transmit_displaynotify(d, "CFwd enabled", 10);
+	} else if (sub->dialType == DIALTYPE_XFER) {
+		ast_copy_string(sub->exten, exten, sizeof(sub->exten));
+		skinny_transfer_blind(sub);
 	}
 }
 
@@ -6117,21 +6097,14 @@
 		}
 	} else {
 		/* We already have a related sub so we can either complete XFER or go into BLINDXFER (or cancel BLINDXFER */
-		if (sub->blindxfer) {
-			/* toggle blindxfer off */
-			sub->blindxfer = 0;
-			sub->related->blindxfer = 0;
-			/* we really need some indications */
+		if (sub->substate == SUBSTATE_OFFHOOK) {
+			if (sub->dialType == DIALTYPE_XFER) {
+				sub->dialType = DIALTYPE_NORMAL;
+			} else {
+				sub->dialType = DIALTYPE_XFER;
+			}
 		} else {
-			/* We were doing attended transfer */
-			if (ast_channel_state(sub->owner) == AST_STATE_DOWN || ast_channel_state(sub->related->owner) == AST_STATE_DOWN) {
-				/* one of the subs so we cant transfer yet, toggle blindxfer on */
-				sub->blindxfer = 1;
-				sub->related->blindxfer = 1;
-			} else {
-				/* big assumption we have two channels, lets transfer */
-				skinny_transfer(sub);
-			}
+			skinny_transfer_attended(sub);
 		}
 	}
 	return 0;

Modified: team/mmichelson/transfer_stasis/channels/chan_unistim.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/channels/chan_unistim.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/channels/chan_unistim.c (original)
+++ team/mmichelson/transfer_stasis/channels/chan_unistim.c Tue Jun 11 11:11:55 2013
@@ -4792,7 +4792,7 @@
 	struct unistim_line *l;
 	struct unistim_device *d;
 	struct unistimsession *s;
-	int i;
+	int i,end_call = 1;
 
 	s = channel_to_session(ast);
 	sub = ast_channel_tech_pvt(ast);
@@ -4835,10 +4835,8 @@
 		unistim_unalloc_sub(d, sub);
 		return 0;
 	}
-
 	if (sub->subtype == SUB_REAL) {
 		sub_stop_silence(s, sub);
-		send_end_call(s); /* Send end call packet only if ending active call, in other way sound should be loosed */
 	} else if (sub->subtype == SUB_RING) {
 		send_no_ring(s);
 		for (i = 0; i < FAVNUM; i++) {
@@ -4849,8 +4847,16 @@
 			if (is_key_line(d, i) && !strcmp(l->name, d->sline[i]->name)) {
 				send_favorite_short(i, FAV_LINE_ICON, s);
 				d->ssub[i] = NULL;
-			}
-		}
+				continue;
+			}
+			if (d->ssub[i] != NULL) { /* Found other subchannel active other then hangup'ed one */
+				ast_log(LOG_WARNING, "There is not only one call here %p %p %i\n",d->ssub[i], sub, i);
+				end_call = 0;
+			}
+		}
+	}
+	if (end_call) {
+		send_end_call(s); /* Send end call packet only if ending active call, in other way sound should be loosed */
 	}
 	sub->moh = 0;
 	if (sub->softkey >= 0) {
@@ -6141,7 +6147,7 @@
 			return 0;
 		}
 		if (d->softkeyicon[p] != 0) {
-			ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used\n:", p);
+			ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used:\n", p);
 			return 0;
 		}
 		memmove(line, line + 2, sizeof(line) - 2);

Modified: team/mmichelson/transfer_stasis/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/configs/queues.conf.sample?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/configs/queues.conf.sample (original)
+++ team/mmichelson/transfer_stasis/configs/queues.conf.sample Tue Jun 11 11:11:55 2013
@@ -316,6 +316,13 @@
 ; will have their position announced.
 ;
 ;announce-position = yes
+;
+; If enabled, play announcements to the first user waiting in the Queue. This may mean
+; that announcements are played when an agent attempts to connect to the waiting user,
+; which may delay the time before the agent and the user can communicate. Disabled by
+; default.
+;
+; announce-to-first-user = no
 ;
 ; If you have specified "limit" or "more" for the announce-position option, then the following
 ; value is what is used to determine what announcement to play to waiting callers. If you have

Modified: team/mmichelson/transfer_stasis/include/asterisk/stasis.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/include/asterisk/stasis.h?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/include/asterisk/stasis.h (original)
+++ team/mmichelson/transfer_stasis/include/asterisk/stasis.h Tue Jun 11 11:11:55 2013
@@ -154,6 +154,8 @@
  * certain loads.
  */
 
+#include "asterisk/json.h"
+#include "asterisk/manager.h"
 #include "asterisk/utils.h"
 
 /*! @{ */
@@ -165,17 +167,58 @@
 struct stasis_message_type;
 
 /*!
- * \brief Register a new message type.
+ * \brief Opaque type for a Stasis message.
+ * \since 12
+ */
+struct stasis_message;
+
+/*!
+ * \brief Virtual table providing methods for messages.
+ * \since 12
+ */
+struct stasis_message_vtable {
+	/*!
+	 * \brief Build the JSON representation of the message.
+	 *
+	 * May be \c NULL, or may return \c NULL, to indicate no representation.
+	 * The returned object should be ast_json_unref()'ed.
+	 *
+	 * \param message Message to convert to JSON string.
+	 * \return Newly allocated JSON message.
+	 * \return \c NULL on error.
+	 * \return \c NULL if JSON format is not supported.
+	 */
+	struct ast_json *(*to_json)(struct stasis_message *message);
+
+	/*!
+	 * \brief Build the AMI representation of the message.
+	 *
+	 * May be \c NULL, or may return \c NULL, to indicate no representation.
+	 * The returned object should be ao2_cleankup()'ed.
+	 *
+	 * \param message Message to convert to AMI string.
+	 * \return Newly allocated \ref ast_manager_event_blob.
+	 * \return \c NULL on error.
+	 * \return \c NULL if AMI format is not supported.
+	 */
+	struct ast_manager_event_blob *(*to_ami)(
+		struct stasis_message *message);
+};
+
+/*!
+ * \brief Create a new message type.
  *
  * \ref stasis_message_type is an AO2 object, so ao2_cleanup() when you're done
  * with it.
  *
  * \param name Name of the new type.
+ * \param vtable Virtual table of message methods. May be \c NULL.
  * \return Pointer to the new type.
  * \return \c NULL on error.
  * \since 12
  */
-struct stasis_message_type *stasis_message_type_create(const char *name);
+struct stasis_message_type *stasis_message_type_create(const char *name,
+	struct stasis_message_vtable *vtable);
 
 /*!
  * \brief Gets the name of a given message type
@@ -187,12 +230,6 @@
 const char *stasis_message_type_name(const struct stasis_message_type *type);
 
 /*!
- * \brief Opaque type for a Stasis message.
- * \since 12
- */
-struct stasis_message;
-
-/*!
  * \brief Create a new message.
  *
  * This message is an \c ao2 object, and must be ao2_cleanup()'ed when you are done
@@ -233,6 +270,32 @@
  * \since 12
  */
 const struct timeval *stasis_message_timestamp(const struct stasis_message *msg);
+
+/*!
+ * \brief Build the JSON representation of the message.
+ *
+ * May return \c NULL, to indicate no representation. The returned object should
+ * be ast_json_unref()'ed.
+ *
+ * \param message Message to convert to JSON string.
+ * \return Newly allocated string with JSON message.
+ * \return \c NULL on error.
+ * \return \c NULL if JSON format is not supported.
+ */
+struct ast_json *stasis_message_to_json(struct stasis_message *message);
+
+/*!
+ * \brief Build the AMI representation of the message.
+ *
+ * May return \c NULL, to indicate no representation. The returned object should
+ * be ao2_cleanup()'ed.
+ *
+ * \param message Message to convert to AMI.
+ * \return \c NULL on error.
+ * \return \c NULL if AMI format is not supported.
+ */
+struct ast_manager_event_blob *stasis_message_to_ami(
+	struct stasis_message *message);
 
 /*! @} */
 
@@ -635,20 +698,37 @@
 /*!
  * \brief Boiler-plate removing macro for defining message types.
  *
+ * \code
+ *	STASIS_MESSAGE_TYPE_DEFN(ast_foo_type,
+ *		.to_ami = foo_to_ami,
+ *		.to_json = foo_to_json,
+ *		);
+ * \endcode
+ *
  * \param name Name of message type.
- * \since 12
- */
-#define STASIS_MESSAGE_TYPE_DEFN(name)				\
-	static struct stasis_message_type *_priv_ ## name;	\
-	struct stasis_message_type *name(void) {		\
-		if (_priv_ ## name == NULL) {			\
-			stasis_log_bad_type_access(#name);	\
-		}						\
-		return _priv_ ## name;				\
+ * \param ... Virtual table methods for messages of this type.
+ * \since 12
+ */
+#define STASIS_MESSAGE_TYPE_DEFN(name, ...)				\
+	static struct stasis_message_vtable _priv_ ## name ## _v = {	\
+		__VA_ARGS__						\
+	};								\
+	static struct stasis_message_type *_priv_ ## name;		\
+	struct stasis_message_type *name(void) {			\
+		if (_priv_ ## name == NULL) {				\
+			stasis_log_bad_type_access(#name);		\
+		}							\
+		return _priv_ ## name;					\
 	}
 
 /*!
- * \brief Boiler-plate removing macro for initializing message types.
+* \brief Boiler-plate removing macro for initializing message types.
+ *
+ * \code
+ *	if (STASIS_MESSAGE_TYPE_INIT(ast_foo_type) != 0) {
+ *		return -1;
+ *	}
+ * \endcode
  *
  * \param name Name of message type.
  * \return 0 if initialization is successful.
@@ -658,8 +738,9 @@
 #define STASIS_MESSAGE_TYPE_INIT(name)					\
 	({								\
 		ast_assert(_priv_ ## name == NULL);			\
-		_priv_ ## name = stasis_message_type_create(#name);	\
-			_priv_ ## name ? 0 : -1;			\
+		_priv_ ## name = stasis_message_type_create(#name,	\
+			&_priv_ ## name ## _v);				\
+		_priv_ ## name ? 0 : -1;				\
 	})
 
 /*!

Modified: team/mmichelson/transfer_stasis/include/asterisk/stasis_app.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/include/asterisk/stasis_app.h?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/include/asterisk/stasis_app.h (original)
+++ team/mmichelson/transfer_stasis/include/asterisk/stasis_app.h Tue Jun 11 11:11:55 2013
@@ -187,6 +187,56 @@
 	enum ast_control_frame_type frame_type);
 
 /*!
+ * \brief Create a bridge of the specified type.
+ *
+ * \param type The type of bridge to be created
+ *
+ * \return New bridge.
+ * \return \c NULL on error.
+ */
+struct ast_bridge *stasis_app_bridge_create(const char *type);
+
+/*!
+ * \brief Returns the bridge with the given id.
+ * \param bridge_id Uniqueid of the bridge.
+ * \return NULL bridge not created by a Stasis application, or bridge does not exist.
+ * \return Pointer to bridge.
+ */
+struct ast_bridge *stasis_app_bridge_find_by_id(
+	const char *bridge_id);
+
+/*!
+ * \brief Add a channel to the bridge.
+ *
+ * \param control Control whose channel should be added to the bridge
+ * \param bridge Pointer to the bridge
+ */
+void stasis_app_control_add_channel_to_bridge(
+	struct stasis_app_control *control, struct ast_bridge *bridge);
+
+/*!
+ * \brief Remove a channel from the bridge.
+ *
+ * \param control Control whose channel should be removed from the bridge
+ * \param bridge Pointer to the bridge
+ *
+ * \retval non-zero on failure
+ * \retval zero on success
+ */
+int stasis_app_control_remove_channel_from_bridge(
+	struct stasis_app_control *control, struct ast_bridge *bridge);
+
+/*!
+ * \brief Destroy the bridge.
+ *
+ * \param bridge_id Uniqueid of bridge to be destroyed
+ *
+ * \retval non-zero on failure
+ * \retval zero on success
+ */
+void stasis_app_bridge_destroy(const char *bridge_id);
+
+/*!
  * \brief Increment the res_stasis reference count.
  *
  * This ensures graceful shutdown happens in the proper order.

Modified: team/mmichelson/transfer_stasis/include/asterisk/stasis_bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/include/asterisk/stasis_bridging.h?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/include/asterisk/stasis_bridging.h (original)
+++ team/mmichelson/transfer_stasis/include/asterisk/stasis_bridging.h Tue Jun 11 11:11:55 2013
@@ -392,6 +392,18 @@
 		struct ast_bridge_channel_pair *locals[2]);
 
 /*!
+ * \brief Returns the most recent snapshot for the bridge.
+ *
+ * The returned pointer is AO2 managed, so ao2_cleanup() when you're done.
+ *
+ * \param bridge_id Uniqueid of the bridge for which to get the snapshot.
+ * \return Most recent snapshot. ao2_cleanup() when done.
+ * \return \c NULL if channel isn't in cache.
+ */
+struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(
+	const char *bridge_id);
+
+/*!
  * \brief Initialize the stasis bridging topic and message types
  * \retval 0 on success
  * \retval -1 on failure

Modified: team/mmichelson/transfer_stasis/main/features_config.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/features_config.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/features_config.c (original)
+++ team/mmichelson/transfer_stasis/main/features_config.c Tue Jun 11 11:11:55 2013
@@ -1168,6 +1168,13 @@
 	return pickup_set(pickup, var->name, var->value);
 }
 
+static int unsupported_handler(const struct aco_option *opt,
+		struct ast_variable *var, void *obj)
+{
+	ast_log(LOG_WARNING, "The option '%s' is no longer configurable in features.conf.\n", var->name);
+	return 0;
+}
+
 static int featuremap_handler(const struct aco_option *opt,
 		struct ast_variable *var, void *obj)
 {
@@ -1378,6 +1385,41 @@
 	aco_option_register_custom(&cfg_info, "pickupfailsound", ACO_EXACT, global_options,
 			DEFAULT_PICKUPFAILSOUND, pickup_handler, 0);
 
+	aco_option_register_custom(&cfg_info, "context", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkext", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkext_exclusive", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkinghints", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkedmusicclass", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkingtime", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkpos", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "findslot", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkedcalltransfers", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkedcallreparking", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkedcallhangup", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkedcallrecording", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "comebackcontext", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "comebacktoorigin", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "comebackdialtime", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "parkeddynamic", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+	aco_option_register_custom(&cfg_info, "adsipark", ACO_EXACT, global_options,
+			"", unsupported_handler, 0);
+
 	aco_option_register_custom(&cfg_info, "blindxfer", ACO_EXACT, featuremap_options,
 			DEFAULT_FEATUREMAP_BLINDXFER, featuremap_handler, 0);
 	aco_option_register_custom(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,

Modified: team/mmichelson/transfer_stasis/main/loader.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/loader.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/loader.c (original)
+++ team/mmichelson/transfer_stasis/main/loader.c Tue Jun 11 11:11:55 2013
@@ -750,7 +750,7 @@
 	event_object = ast_json_pack("{s: s, s: s}",
 			"Module", S_OR(name, "All"),
 			"Status", res_buffer);
-	json_object = ast_json_pack("{s: s, s: i, s: o}",
+	json_object = ast_json_pack("{s: s, s: i, s: O}",
 			"type", "Reload",
 			"class_type", EVENT_FLAG_SYSTEM,
 			"event", event_object);

Modified: team/mmichelson/transfer_stasis/main/manager.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/manager.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/manager.c (original)
+++ team/mmichelson/transfer_stasis/main/manager.c Tue Jun 11 11:11:55 2013
@@ -1311,6 +1311,23 @@
 	}
 
 	return output_str;
+}
+
+static void manager_default_msg_cb(void *data, struct stasis_subscription *sub,
+				    struct stasis_topic *topic,
+				    struct stasis_message *message)
+{
+	RAII_VAR(struct ast_manager_event_blob *, ev, NULL, ao2_cleanup);
+
+	ev = stasis_message_to_ami(message);
+
+	if (ev == NULL) {
+		/* Not and AMI message; disregard */
+		return;
+	}
+
+	manager_event(ev->event_flags, ev->manager_event, "%s",
+		ev->extra_fields);
 }
 
 static void manager_generic_msg_cb(void *data, struct stasis_subscription *sub,
@@ -7686,7 +7703,12 @@
  */
 static int manager_subscriptions_init(void)
 {
-	STASIS_MESSAGE_TYPE_INIT(ast_manager_get_generic_type);
+	int res;
+
+	res = STASIS_MESSAGE_TYPE_INIT(ast_manager_get_generic_type);
+	if (res != 0) {
+		return -1;
+	}
 	manager_topic = stasis_topic_create("manager_topic");
 	if (!manager_topic) {
 		return -1;
@@ -7696,10 +7718,13 @@
 		return -1;
 	}
 
-	if (stasis_message_router_add(stasis_router,
-					 ast_manager_get_generic_type(),
-					 manager_generic_msg_cb,
-					 NULL)) {
+	res |= stasis_message_router_set_default(stasis_router,
+		manager_default_msg_cb, NULL);
+
+	res |= stasis_message_router_add(stasis_router,
+		ast_manager_get_generic_type(), manager_generic_msg_cb, NULL);
+
+	if (res != 0) {
 		return -1;
 	}
 	return 0;

Modified: team/mmichelson/transfer_stasis/main/manager_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/manager_channels.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/manager_channels.c (original)
+++ team/mmichelson/transfer_stasis/main/manager_channels.c Tue Jun 11 11:11:55 2013
@@ -710,49 +710,6 @@
 	}
 }
 
-static void channel_varset_cb(void *data, struct stasis_subscription *sub,
-	struct stasis_topic *topic, struct stasis_message *message)
-{
-	struct ast_channel_blob *obj = stasis_message_data(message);
-	RAII_VAR(struct ast_str *, channel_event_string, NULL, ast_free);
-	const char *variable = ast_json_string_get(ast_json_object_get(obj->blob, "variable"));
-	const char *value = ast_json_string_get(ast_json_object_get(obj->blob, "value"));
-
-	if (obj->snapshot) {
-		channel_event_string = ast_manager_build_channel_state_string(obj->snapshot);
-	} else {
-		channel_event_string = ast_str_create(35);
-		ast_str_set(&channel_event_string, 0,
-			    "Channel: none\r\n"
-			    "Uniqueid: none\r\n");
-	}
-
-	if (!channel_event_string) {
-		return;
-	}
-
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a variable is set to a particular value.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
-				<parameter name="Variable">
-					<para>The variable being set.</para>
-				</parameter>
-				<parameter name="Value">
-					<para>The new value of the variable.</para>
-				</parameter>
-			</syntax>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
-		      "%s"
-		      "Variable: %s\r\n"
-		      "Value: %s\r\n",
-		      ast_str_buffer(channel_event_string),
-		      variable, value);
-}
-
 static int userevent_exclusion_cb(const char *key)
 {
 	if (!strcmp("type", key)) {
@@ -1280,11 +1237,6 @@
 					 NULL);
 
 	ret |= stasis_message_router_add(message_router,
-					 ast_channel_varset_type(),
-					 channel_varset_cb,
-					 NULL);
-
-	ret |= stasis_message_router_add(message_router,
 					 ast_channel_user_event_type(),
 					 channel_user_event_cb,
 					 NULL);

Modified: team/mmichelson/transfer_stasis/main/parking.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/parking.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/parking.c (original)
+++ team/mmichelson/transfer_stasis/main/parking.c Tue Jun 11 11:11:55 2013
@@ -35,7 +35,7 @@
 #include "asterisk/channel.h"
 
 /*! \brief Message type for parked calls */
-static struct stasis_message_type *parked_call_type;
+STASIS_MESSAGE_TYPE_DEFN(ast_parked_call_type);
 
 /*! \brief Topic for parking lots */
 static struct stasis_topic *parking_topic;
@@ -48,26 +48,20 @@
 
 void ast_parking_stasis_init(void)
 {
-	parked_call_type = stasis_message_type_create("ast_parked_call");
+	STASIS_MESSAGE_TYPE_INIT(ast_parked_call_type);
 	parking_topic = stasis_topic_create("ast_parking");
 }
 
 void ast_parking_stasis_disable(void)
 {
-	ao2_cleanup(parked_call_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_parked_call_type);
 	ao2_cleanup(parking_topic);
-	parked_call_type = NULL;
 	parking_topic = NULL;
 }
 
 struct stasis_topic *ast_parking_topic(void)
 {
 	return parking_topic;
-}
-
-struct stasis_message_type *ast_parked_call_type(void)
-{
-	return parked_call_type;
 }
 
 /*! \brief Destructor for parked_call_payload objects */

Modified: team/mmichelson/transfer_stasis/main/stasis_bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/stasis_bridging.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/stasis_bridging.c (original)
+++ team/mmichelson/transfer_stasis/main/stasis_bridging.c Tue Jun 11 11:11:55 2013
@@ -539,6 +539,28 @@
 	stasis_publish(ast_bridge_topic_all(), msg);
 }
 
+struct ast_bridge_snapshot *ast_bridge_snapshot_get_latest(const char *uniqueid)
+{
+	RAII_VAR(struct stasis_message *, message, NULL, ao2_cleanup);
+	struct ast_bridge_snapshot *snapshot;
+
+	ast_assert(!ast_strlen_zero(uniqueid));
+
+	message = stasis_cache_get(ast_bridge_topic_all_cached(),
+			ast_bridge_snapshot_type(),
+			uniqueid);
+	if (!message) {
+		return NULL;
+	}
+
+	snapshot = stasis_message_data(message);
+	if (!snapshot) {
+		return NULL;
+	}
+	ao2_ref(snapshot, +1);
+	return snapshot;
+}
+
 static void stasis_bridging_cleanup(void)
 {
 	ao2_cleanup(bridge_topic_all);

Modified: team/mmichelson/transfer_stasis/main/stasis_channels.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer_stasis/main/stasis_channels.c?view=diff&rev=391405&r1=391404&r2=391405
==============================================================================
--- team/mmichelson/transfer_stasis/main/stasis_channels.c (original)
+++ team/mmichelson/transfer_stasis/main/stasis_channels.c Tue Jun 11 11:11:55 2013
@@ -36,29 +36,24 @@
 #include "asterisk/astobj2.h"
 #include "asterisk/stasis_channels.h"
 
+/*** DOCUMENTATION
+	<managerEvent language="en_US" name="VarSet">
+		<managerEventInstance class="EVENT_FLAG_DIALPLAN">
+			<synopsis>Raised when a variable is set to a particular value.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="Variable">
+					<para>The variable being set.</para>
+				</parameter>
+				<parameter name="Value">
+					<para>The new value of the variable.</para>
+				</parameter>
+			</syntax>
+		</managerEventInstance>
+	</managerEvent>
+***/
+
 #define NUM_MULTI_CHANNEL_BLOB_BUCKETS 7
-
-/*!
- * @{ \brief Define channel message types.
- */
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_snapshot_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_dial_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_varset_type);
-STASIS_MESSAGE_TYPE_DEFN(ast_channel_user_event_type);

[... 1685 lines stripped ...]



More information about the asterisk-commits mailing list