[svn-commits] mmichelson: branch mmichelson/features_config_docs r391478 - in /team/mmichel...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Tue Jun 11 20:02:04 CDT 2013


Author: mmichelson
Date: Tue Jun 11 20:02:02 2013
New Revision: 391478

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=391478
Log:
Get merged up. This code is ready for review!


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

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

Propchange: team/mmichelson/features_config_docs/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Jun 11 20:02:02 2013
@@ -1,1 +1,1 @@
-/trunk:1-391009
+/trunk:1-391477

Modified: team/mmichelson/features_config_docs/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/UPGRADE.txt?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/UPGRADE.txt (original)
+++ team/mmichelson/features_config_docs/UPGRADE.txt Tue Jun 11 20:02:02 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/features_config_docs/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/apps/app_queue.c?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/apps/app_queue.c (original)
+++ team/mmichelson/features_config_docs/apps/app_queue.c Tue Jun 11 20:02:02 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/features_config_docs/bridges/bridge_native_rtp.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/bridges/bridge_native_rtp.c?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/bridges/bridge_native_rtp.c (original)
+++ team/mmichelson/features_config_docs/bridges/bridge_native_rtp.c Tue Jun 11 20:02:02 2013
@@ -87,7 +87,7 @@
 {
 	if (ast_channel_monitor(chan) || (ast_channel_audiohooks(chan) &&
 		!ast_audiohook_write_list_empty(ast_channel_audiohooks(chan))) ||
-		!ast_framehook_list_is_empty(ast_channel_framehooks(chan))) {
+		!ast_framehook_list_contains_no_active(ast_channel_framehooks(chan))) {
 		return 0;
 	} else {
 		return 1;
@@ -317,7 +317,8 @@
 		glue1->get_codec(c1->chan, cap1);
 	}
 
-	if (native_type == AST_RTP_GLUE_RESULT_LOCAL) {
+	switch (native_type) {
+	case AST_RTP_GLUE_RESULT_LOCAL:
 		if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
 			ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, instance1);
 		}
@@ -326,9 +327,14 @@
 		}
 		ast_rtp_instance_set_bridged(instance0, instance1);
 		ast_rtp_instance_set_bridged(instance1, instance0);
-	} else {
+		break;
+
+	case AST_RTP_GLUE_RESULT_REMOTE:
 		glue0->update_peer(c0->chan, instance1, vinstance1, tinstance1, cap1, 0);
 		glue1->update_peer(c1->chan, instance0, vinstance0, tinstance0, cap0, 0);
+		break;
+	case AST_RTP_GLUE_RESULT_FORBID:
+		break;
 	}
 
 	return 0;
@@ -354,7 +360,8 @@
 
 	native_type = native_rtp_bridge_get(c0->chan, c1 ? c1->chan : NULL, &glue0, &glue1, &instance0, &instance1, &vinstance0, &vinstance1);
 
-	if (native_type == AST_RTP_GLUE_RESULT_LOCAL) {
+	switch (native_type) {
+	case AST_RTP_GLUE_RESULT_LOCAL:
 		if (ast_rtp_instance_get_engine(instance0)->local_bridge) {
 			ast_rtp_instance_get_engine(instance0)->local_bridge(instance0, NULL);
 		}
@@ -365,11 +372,15 @@
 		if (instance1) {
 			ast_rtp_instance_set_bridged(instance1, instance0);
 		}
-	} else {
+		break;
+	case AST_RTP_GLUE_RESULT_REMOTE:
 		glue0->update_peer(c0->chan, NULL, NULL, NULL, NULL, 0);
 		if (glue1) {
 			glue1->update_peer(c1->chan, NULL, NULL, NULL, NULL, 0);
 		}
+		break;
+	case AST_RTP_GLUE_RESULT_FORBID:
+		break;
 	}
 }
 

Modified: team/mmichelson/features_config_docs/channels/chan_iax2.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/channels/chan_iax2.c?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/channels/chan_iax2.c (original)
+++ team/mmichelson/features_config_docs/channels/chan_iax2.c Tue Jun 11 20:02:02 2013
@@ -11204,65 +11204,99 @@
 				}
 				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) {
+					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) {
-					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);
+					while (ast_mutex_trylock(&iaxsl[iaxs[fr->callno]->bridgecallno])) {
+						DEADLOCK_AVOIDANCE(&iaxsl[fr->callno]);
+					}
+					if (!iaxs[fr->callno]) {
+						break;
 					}
 				}
-				break;
-			case IAX_COMMAND_TXREADY:
-				if ((iaxs[fr->callno]->transferring == TRANSFER_BEGIN) ||
-				    (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)) {
-					if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN)
-						iaxs[fr->callno]->transferring = TRANSFER_MREADY;
-					else
-						iaxs[fr->callno]->transferring = TRANSFER_READY;
-					ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>");
+
+				if (iaxs[fr->callno]->transferring == TRANSFER_BEGIN) {
+					iaxs[fr->callno]->transferring = TRANSFER_READY;
+				} else if (iaxs[fr->callno]->transferring == TRANSFER_MBEGIN) {
+					iaxs[fr->callno]->transferring = TRANSFER_MREADY;
+				} else {
 					if (iaxs[fr->callno]->bridgecallno) {
-						if ((iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) ||
-						    (iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
-							/* They're both ready, now release them. */
-							if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
-								ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>",
-										iaxs[iaxs[fr->callno]->bridgecallno]->owner ? ast_channel_name(iaxs[iaxs[fr->callno]->bridgecallno]->owner) : "<Unknown>");
-
-								iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
-								iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
-
-								memset(&ied0, 0, sizeof(ied0));
-								memset(&ied1, 0, sizeof(ied1));
-								iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
-								iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
-								send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
-								send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
-							} else {
-								ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>",
-										iaxs[iaxs[fr->callno]->bridgecallno]->owner ? ast_channel_name(iaxs[iaxs[fr->callno]->bridgecallno]->owner) : "<Unknown>");
-
-								iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
-								iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
-								ast_set_flag64(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
-								ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
-
-								/* Stop doing lag & ping requests */
-								stop_stuff(fr->callno);
-								stop_stuff(iaxs[fr->callno]->bridgecallno);
-
-								memset(&ied0, 0, sizeof(ied0));
-								memset(&ied1, 0, sizeof(ied1));
-								iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
-								iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
-								send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
-								send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
-							}
-
-						}
+						ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
 					}
+					break;
 				}
+				ast_verb(3, "Channel '%s' ready to transfer\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>");
+
+				if (!iaxs[fr->callno]->bridgecallno) {
+					break;
+				}
+
+				if (!(iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_READY) &&
+				    !(iaxs[iaxs[fr->callno]->bridgecallno]->transferring == TRANSFER_MREADY)) {
+					ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
+					break;
+				}
+
+				/* Both sides are ready */
+
+				/* XXX what isn't checked here is that both sides match transfer types. */
+
+				if (iaxs[fr->callno]->transferring == TRANSFER_MREADY) {
+					ast_verb(3, "Attempting media bridge of %s and %s\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>",
+							iaxs[iaxs[fr->callno]->bridgecallno]->owner ? ast_channel_name(iaxs[iaxs[fr->callno]->bridgecallno]->owner) : "<Unknown>");
+
+					iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_MEDIA;
+					iaxs[fr->callno]->transferring = TRANSFER_MEDIA;
+
+					memset(&ied0, 0, sizeof(ied0));
+					memset(&ied1, 0, sizeof(ied1));
+					iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
+					iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
+					send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied0.buf, ied0.pos, -1);
+					send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXMEDIA, 0, ied1.buf, ied1.pos, -1);
+				} else {
+					ast_verb(3, "Releasing %s and %s\n", iaxs[fr->callno]->owner ? ast_channel_name(iaxs[fr->callno]->owner) : "<Unknown>",
+							iaxs[iaxs[fr->callno]->bridgecallno]->owner ? ast_channel_name(iaxs[iaxs[fr->callno]->bridgecallno]->owner) : "<Unknown>");
+
+					iaxs[iaxs[fr->callno]->bridgecallno]->transferring = TRANSFER_RELEASED;
+					iaxs[fr->callno]->transferring = TRANSFER_RELEASED;
+					ast_set_flag64(iaxs[iaxs[fr->callno]->bridgecallno], IAX_ALREADYGONE);
+					ast_set_flag64(iaxs[fr->callno], IAX_ALREADYGONE);
+
+					/* Stop doing lag & ping requests */
+					stop_stuff(fr->callno);
+					stop_stuff(iaxs[fr->callno]->bridgecallno);
+
+					memset(&ied0, 0, sizeof(ied0));
+					memset(&ied1, 0, sizeof(ied1));
+					iax_ie_append_short(&ied0, IAX_IE_CALLNO, iaxs[iaxs[fr->callno]->bridgecallno]->peercallno);
+					iax_ie_append_short(&ied1, IAX_IE_CALLNO, iaxs[fr->callno]->peercallno);
+					send_command(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied0.buf, ied0.pos, -1);
+					send_command(iaxs[iaxs[fr->callno]->bridgecallno], AST_FRAME_IAX, IAX_COMMAND_TXREL, 0, ied1.buf, ied1.pos, -1);
+				}
+				ast_mutex_unlock(&iaxsl[iaxs[fr->callno]->bridgecallno]);
 				break;
 			case IAX_COMMAND_TXREQ:
 				try_transfer(iaxs[fr->callno], &ies);

Modified: team/mmichelson/features_config_docs/channels/chan_skinny.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/channels/chan_skinny.c?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/channels/chan_skinny.c (original)
+++ team/mmichelson/features_config_docs/channels/chan_skinny.c Tue Jun 11 20:02:02 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/features_config_docs/channels/chan_unistim.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/channels/chan_unistim.c?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/channels/chan_unistim.c (original)
+++ team/mmichelson/features_config_docs/channels/chan_unistim.c Tue Jun 11 20:02:02 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/features_config_docs/configs/queues.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/configs/queues.conf.sample?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/configs/queues.conf.sample (original)
+++ team/mmichelson/features_config_docs/configs/queues.conf.sample Tue Jun 11 20:02:02 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/features_config_docs/include/asterisk/framehook.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/include/asterisk/framehook.h?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/include/asterisk/framehook.h (original)
+++ team/mmichelson/features_config_docs/include/asterisk/framehook.h Tue Jun 11 20:02:02 2013
@@ -222,7 +222,7 @@
  * \param chan ast_channel The channel to attach the hook on to.
  * \param i framehook interface, The framehook's callback functions and stored data.
  *
- * \pre XXX The Channel must be locked during this function all.
+ * \pre The Channel must be locked during this function all.
  *
  * \note The data pointer is never touched by the framehook API except to
  * provide it during the event and destruction callbacks.  It is entirely up to the
@@ -237,7 +237,7 @@
  * \brief Detach an framehook from a channel.
  * \since 1.8
  * 
- * \pre XXX The Channel must be locked during this function all.
+ * \pre The Channel must be locked during this function all.
  * If this function is never called after attaching an framehook,
  * the framehook will be detached and destroyed during channel
  * destruction.
@@ -256,7 +256,7 @@
  * framehooks on a channel during channel destruction.
  * \since 1.8
  *
- * \pre XXX The Channel must be locked during this function all.
+ * \pre The Channel must be locked during this function all.
  * 
  * \param chan channel containing the framehook list to destroy.
  * \retval 0 success
@@ -272,7 +272,7 @@
  * even NULL.  There is nothing to keep up with after this function. If the frame is modified, the
  * framehook callback is in charge of any memory management associated with that modification.
  *
- * \pre XXX The Channel must be locked during this function all.
+ * \pre The Channel must be locked during this function all.
  *
  * \param framehooks list to push event to.
  * \param frame being pushed to the framehook list.
@@ -289,7 +289,7 @@
  * even NULL.  There is nothing to keep up with after this function. If the frame is modified, the
  * framehook callback is in charge of any memory management associated with that modification.
  *
- * \pre XXX The Channel must be locked during this function all.
+ * \pre The Channel must be locked during this function all.
  *
  * \param framehooks list to push event to.
  * \param frame being pushed to the framehook list.
@@ -301,11 +301,26 @@
 /*!
  * \brief Determine if an framehook list is empty or not
  * \since 1.8
- * \pre XXX The Channel must be locked during this function all.
+ * \pre The Channel must be locked during this function all.
  *
  * \param framehooks the framehook list
  * \retval 0, not empty
  * \retval 1, is empty
  */
 int ast_framehook_list_is_empty(struct ast_framehook_list *framehooks);
+
+/*!
+ * \brief Determine if a framehook list is free of active framehooks or not
+ * \since 12.0.0
+ * \pre The channel must be locked during this function all.
+ *
+ * \param framehooks the framehook list
+ * \retval 0, not empty
+ * \retval 1, is empty (aside from dying framehooks)
+ *
+ * \note This function is very similar to ast_framehook_list_is_empty, but it checks individual
+ *       framehooks to see if they have been marked for destruction and doesn't count them if they are.
+ */
+int ast_framehook_list_contains_no_active(struct ast_framehook_list *framehooks);
+
 #endif /* _AST_FRAMEHOOK_H */

Modified: team/mmichelson/features_config_docs/include/asterisk/lock.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/include/asterisk/lock.h?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/include/asterisk/lock.h (original)
+++ team/mmichelson/features_config_docs/include/asterisk/lock.h Tue Jun 11 20:02:02 2013
@@ -59,6 +59,7 @@
 #include "asterisk/time.h"
 #endif
 
+#include "asterisk/backtrace.h"
 #include "asterisk/logger.h"
 #include "asterisk/compiler.h"
 

Modified: team/mmichelson/features_config_docs/include/asterisk/logger.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/include/asterisk/logger.h?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/include/asterisk/logger.h (original)
+++ team/mmichelson/features_config_docs/include/asterisk/logger.h Tue Jun 11 20:02:02 2013
@@ -80,7 +80,10 @@
 void ast_log_callid(int level, const char *file, int line, const char *function, struct ast_callid *callid, const char *fmt, ...)
 	__attribute__((format(printf, 6, 7)));
 
-void ast_backtrace(void);
+/*!
+ * \brief Log a backtrace of the current thread's execution stack to the Asterisk log
+ */
+void ast_log_backtrace(void);
 
 /*! \brief Reload logger without rotating log files */
 int logger_reload(void);
@@ -362,63 +365,6 @@
 #define ast_verb(level, ...) __ast_verbose(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, __VA_ARGS__)
 #define ast_verb_callid(level, callid, ...) __ast_verbose_callid(__FILE__, __LINE__, __PRETTY_FUNCTION__, level, callid, __VA_ARGS__)
 
-#ifndef _LOGGER_BACKTRACE_H
-#define _LOGGER_BACKTRACE_H
-#ifdef HAVE_BKTR
-#define AST_MAX_BT_FRAMES 32
-/* \brief
- *
- * A structure to hold backtrace information. This structure provides an easy means to
- * store backtrace information or pass backtraces to other functions.
- */
-struct ast_bt {
-	/*! The addresses of the stack frames. This is filled in by calling the glibc backtrace() function */
-	void *addresses[AST_MAX_BT_FRAMES];
-	/*! The number of stack frames in the backtrace */
-	int num_frames;
-	/*! Tells if the ast_bt structure was dynamically allocated */
-	unsigned int alloced:1;
-};
-
-/* \brief
- * Allocates memory for an ast_bt and stores addresses and symbols.
- *
- * \return Returns NULL on failure, or the allocated ast_bt on success
- * \since 1.6.1
- */
-struct ast_bt *ast_bt_create(void);
-
-/* \brief
- * Fill an allocated ast_bt with addresses
- *
- * \retval 0 Success
- * \retval -1 Failure
- * \since 1.6.1
- */
-int ast_bt_get_addresses(struct ast_bt *bt);
-
-/* \brief
- *
- * Free dynamically allocated portions of an ast_bt
- *
- * \retval NULL.
- * \since 1.6.1
- */
-void *ast_bt_destroy(struct ast_bt *bt);
-
-/* \brief Retrieve symbols for a set of backtrace addresses
- *
- * \param addresses A list of addresses, such as the ->addresses structure element of struct ast_bt.
- * \param num_frames Number of addresses in the addresses list
- * \retval NULL Unable to allocate memory
- * \return List of strings
- * \since 1.6.2.16
- */
-char **ast_bt_get_symbols(void **addresses, size_t num_frames);
-
-#endif /* HAVE_BKTR */
-#endif /* _LOGGER_BACKTRACE_H */
-
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: team/mmichelson/features_config_docs/include/asterisk/stasis.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/features_config_docs/include/asterisk/stasis.h?view=diff&rev=391478&r1=391477&r2=391478
==============================================================================
--- team/mmichelson/features_config_docs/include/asterisk/stasis.h (original)
+++ team/mmichelson/features_config_docs/include/asterisk/stasis.h Tue Jun 11 20:02:02 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.

[... 2595 lines stripped ...]



More information about the svn-commits mailing list