? .cvsignore
? advxfer.diff
? core.16836
? core.20120
? core.20219
? core.20736
? core.2312
? core.7632
? dialplanTransfer.diff
? res/res_features2.c
Index: pbx.c
===================================================================
RCS file: /usr/cvsroot/asterisk/pbx.c,v
retrieving revision 1.173
diff -u -r1.173 pbx.c
--- pbx.c	19 Nov 2004 05:18:10 -0000	1.173
+++ pbx.c	20 Nov 2004 18:21:36 -0000
@@ -5469,3 +5469,40 @@
 	return res;
 }
 
+int ast_pbx_transfer(struct ast_channel *xferer,struct ast_channel *xferee,	char * xferer_context, char * xferto_exten)
+{
+	if (!ast_exists_extension(xferer, xferer_context,          "X", 1 , xferer->cid.cid_num))
+		return -1;   /* no transfer extension in the dialplan */
+
+	if (!ast_exists_extension(xferer, xferer_context, xferto_exten, 1, xferer->cid.cid_num))
+		return -2;   /* unknown xferto extension */
+
+	ast_log(LOG_DEBUG, "xferer<%s> xferee<%s> xferto_exten<%s>in context<%s>\n"
+					, xferer->name, xferee->name, xferto_exten, xferer_context);
+	
+	char data[1024];
+	strcpy(data, "X@");
+	strncat(data, xferer_context, sizeof(data) - strlen(data) - 1);
+	strncat(data, "/n", sizeof(data) - strlen(data) - 1);
+	int reason;
+	char var[1024];
+	strcpy(var, "TRANSFERER=");
+	strncat(var, xferer->name, sizeof(var) - strlen(var) - 1);
+	strncat(var, "|TRANSFEREE=", sizeof(var) - strlen(var) - 1);
+	strncat(var, xferee->name, sizeof(var) - strlen(var) - 1);
+	strncat(var, "|TRANSFERTO_EXTEN=", sizeof(var) - strlen(var) - 1);
+	strncat(var, xferto_exten, sizeof(var) - strlen(var) - 1);
+	
+	if( !ast_pbx_outgoing_exten("Local", AST_FORMAT_SLINEAR, data, 
+															5000, 
+															xferer_context, "X", 1, 
+															&reason, 
+															//0,          // asynchronous
+															1,          // synchronous
+															NULL, NULL, // don't care about the cid
+															var, 
+															NULL))      // don't care about the account
+		return 0;
+	else
+		return -3;
+}
Index: channels/chan_iax2.c
===================================================================
RCS file: /usr/cvsroot/asterisk/channels/chan_iax2.c,v
retrieving revision 1.216
diff -u -r1.216 chan_iax2.c
--- channels/chan_iax2.c	17 Nov 2004 03:10:38 -0000	1.216
+++ channels/chan_iax2.c	20 Nov 2004 18:21:54 -0000
@@ -5558,6 +5558,8 @@
 						} else
 							ast_log(LOG_DEBUG, "Parked call on '%s'\n", ast_bridged_channel(iaxs[fr.callno]->owner)->name);
 					} else {
+						if(!ast_pbx_transfer(iaxs[fr.callno]->owner, ast_bridged_channel(iaxs[fr.callno]->owner), iaxs[fr.callno]->context, ies.called_number))
+							break;
 						if (ast_async_goto(ast_bridged_channel(iaxs[fr.callno]->owner), iaxs[fr.callno]->context, ies.called_number, 1))
 							ast_log(LOG_WARNING, "Async goto of '%s' to '%s@%s' failed\n", ast_bridged_channel(iaxs[fr.callno]->owner)->name, 
 								ies.called_number, iaxs[fr.callno]->context);
Index: include/asterisk/pbx.h
===================================================================
RCS file: /usr/cvsroot/asterisk/include/asterisk/pbx.h,v
retrieving revision 1.33
diff -u -r1.33 pbx.h
--- include/asterisk/pbx.h	13 Nov 2004 22:44:33 -0000	1.33
+++ include/asterisk/pbx.h	20 Nov 2004 18:21:57 -0000
@@ -579,6 +579,11 @@
   fall through (reads extension instead).  Returns previous value. */
 extern int pbx_set_autofallthrough(int newval);
 
+/* Dialplan transfer. If the 'X' extension exists, this extension will be ringed  by a local channel
+	 whose local variables will describe what transfer to make. Returns 0 if 'X' was ringed */
+int ast_pbx_transfer(struct ast_channel *xferer, struct ast_channel *xferee,	char * xferer_context, char * xferto_exten);
+
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
Index: res/res_features.c
===================================================================
RCS file: /usr/cvsroot/asterisk/res/res_features.c,v
retrieving revision 1.21
diff -u -r1.21 res_features.c
--- res/res_features.c	3 Nov 2004 22:37:55 -0000	1.21
+++ res/res_features.c	20 Nov 2004 18:21:59 -0000
@@ -290,7 +290,6 @@
 {
 	/* Copy voice back and forth between the two channels.  Give the peer
 	   the ability to transfer calls with '#<extension' syntax. */
-	int len;
 	struct ast_frame *f;
 	struct ast_channel *who;
 	char newext[256], *ptr;
@@ -455,20 +454,19 @@
 					/* If they've typed a digit already, handle it */
 					newext[0] = res;
 					ptr++;
-					len --;
 				}
 				res = 0;
 				while (strlen(newext) < sizeof(newext) - 1) {
+					if(newext[0]=='#')   /* early double # */
+						break;
 					res = ast_waitfordigit(transferer, transferdigittimeout);
 					if (res < 1) 
 						break;
-					if (res == '#')
+					if (res == '#')      /* double # or end of extension */
 						break;
 					*(ptr++) = res;
-					if (!ast_matchmore_extension(transferer, transferer_real_context
-								, newext, 1, transferer->cid.cid_num)) {
+					if (!ast_matchmore_extension(transferer, transferer_real_context, newext, 1, transferer->cid.cid_num))
 						break;
-					}
 				}
 
 				if (res < 0) {
@@ -476,6 +474,19 @@
 					ast_autoservice_stop(transferee);
 					break;
 				}
+
+				// in case of double #
+				if(newext[0]=='#' || strlen(newext)==0) {
+					ast_log(LOG_DEBUG, "double #\n");
+					ast_moh_stop(transferee);
+					ast_autoservice_stop(transferee);
+					if (who == peer)
+						ast_write(chan, f);
+					else
+						ast_write(peer, f);
+					continue;
+				}
+
 				if (!strcmp(newext, ast_parking_ext())) {
 					ast_moh_stop(transferee);
 
@@ -496,6 +507,15 @@
 					}
 					/* XXX Maybe we should have another message here instead of invalid extension XXX */
 				} else if (ast_exists_extension(transferee, transferer_real_context, newext, 1, transferer->cid.cid_num)) {
+					/* first try to a dialplan transfer */
+					if(!ast_pbx_transfer(transferer,transferee,transferer_real_context,newext)) {
+						ast_moh_stop(transferee);
+						ast_autoservice_stop(transferee);
+						ast_frfree(f);
+						continue;
+					}
+
+					/* switch to blind transfer if the dialplan transfer failed */
 					pbx_builtin_setvar_helper(peer, "BLINDTRANSFER", chan->name);
 					pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", peer->name);
 					ast_moh_stop(transferee);
